1 | <?php |
||
2 | |||
3 | /** |
||
4 | * RestController is responsible for handling all the requests directed to the /rest address. |
||
5 | */ |
||
6 | class RestController extends Controller |
||
7 | { |
||
8 | /* supported MIME types that can be used to return RDF data */ |
||
9 | const SUPPORTED_FORMATS = 'application/rdf+xml text/turtle application/ld+json application/json application/marcxml+xml'; |
||
10 | /* context array template */ |
||
11 | private $context = array( |
||
12 | '@context' => array( |
||
13 | 'skos' => 'http://www.w3.org/2004/02/skos/core#', |
||
14 | 'uri' => '@id', |
||
15 | 'type' => '@type', |
||
16 | ), |
||
17 | ); |
||
18 | |||
19 | /** |
||
20 | * Handles json encoding, adding the content type headers and optional callback function. |
||
21 | * @param array $data the data to be returned. |
||
22 | */ |
||
23 | private function returnJson($data) |
||
24 | { |
||
25 | // wrap with JSONP callback if requested |
||
26 | if (filter_input(INPUT_GET, 'callback', FILTER_SANITIZE_FULL_SPECIAL_CHARS)) { |
||
27 | header("Content-type: application/javascript; charset=utf-8"); |
||
28 | echo filter_input(INPUT_GET, 'callback', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_FLAG_NO_ENCODE_QUOTES) . "(" . json_encode($data) . ");"; |
||
29 | return; |
||
30 | } |
||
31 | |||
32 | // otherwise negotiate suitable format for the response and return that |
||
33 | $negotiator = new \Negotiation\Negotiator(); |
||
34 | $priorities = array('application/json', 'application/ld+json'); |
||
35 | $best = filter_input(INPUT_SERVER, 'HTTP_ACCEPT', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ? $negotiator->getBest(filter_input(INPUT_SERVER, 'HTTP_ACCEPT', FILTER_SANITIZE_FULL_SPECIAL_CHARS), $priorities) : null; |
||
36 | $format = ($best !== null) ? $best->getValue() : $priorities[0]; |
||
37 | header("Content-type: $format; charset=utf-8"); |
||
38 | header("Vary: Accept"); // inform caches that we made a choice based on Accept header |
||
39 | echo json_encode($data); |
||
40 | } |
||
41 | |||
42 | /** |
||
43 | * Parses and returns the limit parameter. Returns and error if the parameter is missing. |
||
44 | */ |
||
45 | private function parseLimit() |
||
46 | { |
||
47 | $limit = filter_input(INPUT_GET, 'limit', FILTER_SANITIZE_NUMBER_INT) ? filter_input(INPUT_GET, 'limit', FILTER_SANITIZE_NUMBER_INT) : $this->model->getConfig()->getDefaultTransitiveLimit(); |
||
48 | if ($limit <= 0) { |
||
49 | return $this->returnError(400, "Bad Request", "Invalid limit parameter"); |
||
50 | } |
||
51 | |||
52 | return $limit; |
||
53 | } |
||
54 | |||
55 | |||
56 | /** Global REST methods **/ |
||
57 | |||
58 | /** |
||
59 | * Returns all the vocabularies available on the server in a json object. |
||
60 | */ |
||
61 | public function vocabularies($request) |
||
62 | { |
||
63 | if (!$request->getLang()) { |
||
64 | return $this->returnError(400, "Bad Request", "lang parameter missing"); |
||
65 | } |
||
66 | |||
67 | $this->setLanguageProperties($request->getLang()); |
||
68 | |||
69 | $vocabs = array(); |
||
70 | foreach ($this->model->getVocabularies() as $voc) { |
||
71 | $vocabs[$voc->getId()] = $voc->getConfig()->getTitle($request->getLang()); |
||
72 | } |
||
73 | ksort($vocabs); |
||
74 | $results = array(); |
||
75 | foreach ($vocabs as $id => $title) { |
||
76 | $results[] = array( |
||
77 | 'uri' => $id, |
||
78 | 'id' => $id, |
||
79 | 'title' => $title); |
||
80 | } |
||
81 | |||
82 | /* encode the results in a JSON-LD compatible array */ |
||
83 | $ret = array( |
||
84 | '@context' => array( |
||
85 | 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#', |
||
86 | 'onki' => 'http://schema.onki.fi/onki#', |
||
87 | 'title' => array('@id' => 'rdfs:label', '@language' => $request->getLang()), |
||
88 | 'vocabularies' => 'onki:hasVocabulary', |
||
89 | 'id' => 'onki:vocabularyIdentifier', |
||
90 | 'uri' => '@id', |
||
91 | '@base' => $this->getBaseHref() . "rest/v1/vocabularies", |
||
92 | ), |
||
93 | 'uri' => '', |
||
94 | 'vocabularies' => $results, |
||
95 | ); |
||
96 | |||
97 | return $this->returnJson($ret); |
||
98 | } |
||
99 | |||
100 | private function constructSearchParameters($request) |
||
101 | { |
||
102 | $parameters = new ConceptSearchParameters($request, $this->model->getConfig(), true); |
||
103 | |||
104 | $vocabs = $request->getQueryParam('vocab'); # optional |
||
105 | // convert to vocids array to support multi-vocabulary search |
||
106 | $vocids = ($vocabs !== null && $vocabs !== '') ? explode(' ', $vocabs) : array(); |
||
107 | $vocabObjects = array(); |
||
108 | foreach($vocids as $vocid) { |
||
109 | $vocabObjects[] = $this->model->getVocabulary($vocid); |
||
110 | } |
||
111 | $parameters->setVocabularies($vocabObjects); |
||
112 | return $parameters; |
||
113 | } |
||
114 | |||
115 | private function transformSearchResults($request, $results, $parameters) |
||
116 | { |
||
117 | // before serializing to JSON, get rid of the Vocabulary object that came with each resource |
||
118 | foreach ($results as &$res) { |
||
119 | unset($res['voc']); |
||
120 | } |
||
121 | |||
122 | $context = array( |
||
123 | 'skos' => 'http://www.w3.org/2004/02/skos/core#', |
||
124 | 'isothes' => 'http://purl.org/iso25964/skos-thes#', |
||
125 | 'onki' => 'http://schema.onki.fi/onki#', |
||
126 | 'uri' => '@id', |
||
127 | 'type' => '@type', |
||
128 | 'results' => array( |
||
129 | '@id' => 'onki:results', |
||
130 | '@container' => '@list', |
||
131 | ), |
||
132 | 'prefLabel' => 'skos:prefLabel', |
||
133 | 'altLabel' => 'skos:altLabel', |
||
134 | 'hiddenLabel' => 'skos:hiddenLabel', |
||
135 | ); |
||
136 | foreach ($parameters->getAdditionalFields() as $field) { |
||
137 | |||
138 | // Quick-and-dirty compactification |
||
139 | $context[$field] = 'skos:' . $field; |
||
140 | foreach ($results as &$result) { |
||
141 | foreach ($result as $k => $v) { |
||
142 | if ($k == 'skos:' . $field) { |
||
143 | $result[$field] = $v; |
||
144 | unset($result['skos:' . $field]); |
||
145 | } |
||
146 | } |
||
147 | } |
||
148 | } |
||
149 | |||
150 | $ret = array( |
||
151 | '@context' => $context, |
||
152 | 'uri' => '', |
||
153 | 'results' => $results, |
||
154 | ); |
||
155 | |||
156 | if (isset($results[0]['prefLabels'])) { |
||
157 | $ret['@context']['prefLabels'] = array('@id' => 'skos:prefLabel', '@container' => '@language'); |
||
158 | } |
||
159 | |||
160 | if ($request->getQueryParam('labellang')) { |
||
161 | $ret['@context']['@language'] = $request->getQueryParam('labellang'); |
||
162 | } elseif ($request->getQueryParam('lang')) { |
||
163 | $ret['@context']['@language'] = $request->getQueryParam('lang'); |
||
164 | } |
||
165 | return $ret; |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Performs the search function calls. And wraps the result in a json-ld object. |
||
170 | * @param Request $request |
||
171 | */ |
||
172 | public function search(Request $request): void |
||
173 | { |
||
174 | $maxhits = $request->getQueryParam('maxhits'); |
||
175 | $offset = $request->getQueryParam('offset'); |
||
176 | $term = $request->getQueryParamRaw('query'); |
||
177 | |||
178 | if ((!isset($term) || strlen(trim($term)) === 0) && (!$request->getQueryParam('group') && !$request->getQueryParam('parent'))) { |
||
179 | $this->returnError(400, "Bad Request", "query parameter missing"); |
||
180 | return; |
||
181 | } |
||
182 | if ($maxhits && (!is_numeric($maxhits) || $maxhits <= 0)) { |
||
183 | $this->returnError(400, "Bad Request", "maxhits parameter is invalid"); |
||
184 | return; |
||
185 | } |
||
186 | if ($offset && (!is_numeric($offset) || $offset < 0)) { |
||
187 | $this->returnError(400, "Bad Request", "offset parameter is invalid"); |
||
188 | return; |
||
189 | } |
||
190 | |||
191 | $parameters = $this->constructSearchParameters($request); |
||
192 | $results = $this->model->searchConcepts($parameters); |
||
193 | $ret = $this->transformSearchResults($request, $results, $parameters); |
||
194 | |||
195 | $this->returnJson($ret); |
||
196 | } |
||
197 | |||
198 | /** Vocabulary-specific methods **/ |
||
199 | |||
200 | /** |
||
201 | * Loads the vocabulary metadata. And wraps the result in a json-ld object. |
||
202 | * @param Request $request |
||
203 | */ |
||
204 | public function vocabularyInformation($request) |
||
205 | { |
||
206 | $vocab = $request->getVocab(); |
||
207 | if ($this->notModified($vocab)) { |
||
208 | return null; |
||
209 | } |
||
210 | |||
211 | /* encode the results in a JSON-LD compatible array */ |
||
212 | $conceptschemes = array(); |
||
213 | foreach ($vocab->getConceptSchemes($request->getLang()) as $uri => $csdata) { |
||
214 | $csdata['uri'] = $uri; |
||
215 | $csdata['type'] = 'skos:ConceptScheme'; |
||
216 | $conceptschemes[] = $csdata; |
||
217 | } |
||
218 | |||
219 | $ret = array( |
||
220 | '@context' => array( |
||
221 | 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#', |
||
222 | 'skos' => 'http://www.w3.org/2004/02/skos/core#', |
||
223 | 'onki' => 'http://schema.onki.fi/onki#', |
||
224 | 'dct' => 'http://purl.org/dc/terms/', |
||
225 | 'uri' => '@id', |
||
226 | 'type' => '@type', |
||
227 | 'conceptschemes' => 'onki:hasConceptScheme', |
||
228 | 'id' => 'onki:vocabularyIdentifier', |
||
229 | 'defaultLanguage' => 'onki:defaultLanguage', |
||
230 | 'languages' => 'onki:language', |
||
231 | 'label' => 'rdfs:label', |
||
232 | 'prefLabel' => 'skos:prefLabel', |
||
233 | 'title' => 'dct:title', |
||
234 | '@language' => $request->getLang(), |
||
235 | '@base' => $this->getBaseHref() . "rest/v1/" . $vocab->getId() . "/", |
||
236 | ), |
||
237 | 'uri' => '', |
||
238 | 'id' => $vocab->getId(), |
||
239 | 'marcSource' => $vocab->getConfig()->getMarcSourceCode($request->getLang()), |
||
240 | 'title' => $vocab->getConfig()->getTitle($request->getLang()), |
||
241 | 'defaultLanguage' => $vocab->getConfig()->getDefaultLanguage(), |
||
242 | 'languages' => array_values($vocab->getConfig()->getLanguages()), |
||
243 | 'conceptschemes' => $conceptschemes, |
||
244 | ); |
||
245 | |||
246 | if ($vocab->getConfig()->getTypes($request->getLang())) { |
||
247 | $ret['type'] = $vocab->getConfig()->getTypes($request->getLang()); |
||
248 | } |
||
249 | |||
250 | return $this->returnJson($ret); |
||
251 | } |
||
252 | |||
253 | /** |
||
254 | * Loads the vocabulary metadata. And wraps the result in a json-ld object. |
||
255 | * @param Request $request |
||
256 | */ |
||
257 | public function vocabularyStatistics($request) |
||
258 | { |
||
259 | if ($this->notModified($request->getVocab())) { |
||
260 | return null; |
||
261 | } |
||
262 | $this->setLanguageProperties($request->getLang()); |
||
263 | $arrayClass = $request->getVocab()->getConfig()->getArrayClassURI(); |
||
264 | $groupClass = $request->getVocab()->getConfig()->getGroupClassURI(); |
||
265 | $queryLang = $request->getQueryParam('lang') ?? $request->getLang(); |
||
266 | $vocabStats = $request->getVocab()->getStatistics($queryLang, $arrayClass, $groupClass); |
||
267 | $types = array('http://www.w3.org/2004/02/skos/core#Concept', 'http://www.w3.org/2004/02/skos/core#Collection', $arrayClass, $groupClass); |
||
268 | $subTypes = array(); |
||
269 | foreach ($vocabStats as $subtype) { |
||
270 | if (!in_array($subtype['type'], $types)) { |
||
271 | $subTypes[] = $subtype; |
||
272 | } |
||
273 | } |
||
274 | |||
275 | /* encode the results in a JSON-LD compatible array */ |
||
276 | $ret = array( |
||
277 | '@context' => array( |
||
278 | 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#', |
||
279 | 'skos' => 'http://www.w3.org/2004/02/skos/core#', |
||
280 | 'void' => 'http://rdfs.org/ns/void#', |
||
281 | 'onki' => 'http://schema.onki.fi/onki#', |
||
282 | 'uri' => '@id', |
||
283 | 'id' => 'onki:vocabularyIdentifier', |
||
284 | 'concepts' => 'void:classPartition', |
||
285 | 'label' => 'rdfs:label', |
||
286 | 'class' => array('@id' => 'void:class', '@type' => '@id'), |
||
287 | 'subTypes' => array('@id' => 'void:class', '@type' => '@id'), |
||
288 | 'count' => 'void:entities', |
||
289 | '@language' => $request->getLang(), |
||
290 | '@base' => $this->getBaseHref() . "rest/v1/" . $request->getVocab()->getId() . "/", |
||
291 | ), |
||
292 | 'uri' => '', |
||
293 | 'id' => $request->getVocab()->getId(), |
||
294 | 'title' => $request->getVocab()->getConfig()->getTitle(), |
||
295 | 'concepts' => array( |
||
296 | 'class' => 'http://www.w3.org/2004/02/skos/core#Concept', |
||
297 | 'label' => gettext('skos:Concept'), |
||
298 | 'count' => isset($vocabStats['http://www.w3.org/2004/02/skos/core#Concept']) ? $vocabStats['http://www.w3.org/2004/02/skos/core#Concept']['count'] : 0, |
||
299 | 'deprecatedCount' => isset($vocabStats['http://www.w3.org/2004/02/skos/core#Concept']) ? $vocabStats['http://www.w3.org/2004/02/skos/core#Concept']['deprecatedCount'] : 0, |
||
300 | ), |
||
301 | 'subTypes' => $subTypes, |
||
302 | ); |
||
303 | |||
304 | if (isset($vocabStats['http://www.w3.org/2004/02/skos/core#Collection'])) { |
||
305 | $ret['conceptGroups'] = array( |
||
306 | 'class' => 'http://www.w3.org/2004/02/skos/core#Collection', |
||
307 | 'label' => gettext('skos:Collection'), |
||
308 | 'count' => $vocabStats['http://www.w3.org/2004/02/skos/core#Collection']['count'], |
||
309 | 'deprecatedCount' => $vocabStats['http://www.w3.org/2004/02/skos/core#Collection']['deprecatedCount'], |
||
310 | ); |
||
311 | |||
312 | } else if (isset($vocabStats[$groupClass])) { |
||
313 | $ret['conceptGroups'] = array( |
||
314 | 'class' => $groupClass, |
||
315 | 'label' => isset($vocabStats[$groupClass]['label']) ? $vocabStats[$groupClass]['label'] : gettext(EasyRdf\RdfNamespace::shorten($groupClass)), |
||
316 | 'count' => $vocabStats[$groupClass]['count'], |
||
317 | 'deprecatedCount' => $vocabStats[$groupClass]['deprecatedCount'], |
||
318 | ); |
||
319 | } else if (isset($vocabStats[$arrayClass])) { |
||
320 | $ret['arrays'] = array( |
||
321 | 'class' => $arrayClass, |
||
322 | 'label' => isset($vocabStats[$arrayClass]['label']) ? $vocabStats[$arrayClass]['label'] : gettext(EasyRdf\RdfNamespace::shorten($arrayClass)), |
||
323 | 'count' => $vocabStats[$arrayClass]['count'], |
||
324 | 'deprecatedCount' => $vocabStats[$arrayClass]['deprecatedCount'], |
||
325 | ); |
||
326 | } |
||
327 | |||
328 | return $this->returnJson($ret); |
||
329 | } |
||
330 | |||
331 | /** |
||
332 | * Loads the vocabulary metadata. And wraps the result in a json-ld object. |
||
333 | * @param Request $request |
||
334 | */ |
||
335 | public function labelStatistics($request) |
||
336 | { |
||
337 | if ($this->notModified($request->getVocab())) { |
||
338 | return null; |
||
339 | } |
||
340 | $lang = $request->getLang(); |
||
341 | $this->setLanguageProperties($request->getLang()); |
||
342 | $vocabStats = $request->getVocab()->getLabelStatistics(); |
||
343 | |||
344 | /* encode the results in a JSON-LD compatible array */ |
||
345 | $counts = array(); |
||
346 | foreach ($vocabStats['terms'] as $proplang => $properties) { |
||
347 | $langdata = array('language' => $proplang); |
||
348 | if ($lang) { |
||
349 | $langdata['literal'] = Punic\Language::getName($proplang, $lang); |
||
350 | } |
||
351 | |||
352 | $langdata['properties'] = array(); |
||
353 | foreach ($properties as $prop => $value) { |
||
354 | $langdata['properties'][] = array('property' => $prop, 'labels' => $value); |
||
355 | } |
||
356 | $counts[] = $langdata; |
||
357 | } |
||
358 | |||
359 | $ret = array( |
||
360 | '@context' => array( |
||
361 | 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#', |
||
362 | 'skos' => 'http://www.w3.org/2004/02/skos/core#', |
||
363 | 'void' => 'http://rdfs.org/ns/void#', |
||
364 | 'void-ext' => 'http://ldf.fi/void-ext#', |
||
365 | 'onki' => 'http://schema.onki.fi/onki#', |
||
366 | 'uri' => '@id', |
||
367 | 'id' => 'onki:vocabularyIdentifier', |
||
368 | 'languages' => 'void-ext:languagePartition', |
||
369 | 'language' => 'void-ext:language', |
||
370 | 'properties' => 'void:propertyPartition', |
||
371 | 'labels' => 'void:triples', |
||
372 | '@base' => $this->getBaseHref() . "rest/v1/" . $request->getVocab()->getId() . "/", |
||
373 | ), |
||
374 | 'uri' => '', |
||
375 | 'id' => $request->getVocab()->getId(), |
||
376 | 'title' => $request->getVocab()->getConfig()->getTitle($lang), |
||
377 | 'languages' => $counts, |
||
378 | ); |
||
379 | |||
380 | if ($lang) { |
||
381 | $ret['@context']['literal'] = array('@id' => 'rdfs:label', '@language' => $lang); |
||
382 | } |
||
383 | |||
384 | return $this->returnJson($ret); |
||
385 | } |
||
386 | |||
387 | /** |
||
388 | * Loads the vocabulary type metadata. And wraps the result in a json-ld object. |
||
389 | * @param Request $request |
||
390 | */ |
||
391 | public function types($request) |
||
392 | { |
||
393 | $vocid = $request->getVocab() ? $request->getVocab()->getId() : null; |
||
394 | if ($vocid === null && !$request->getLang()) { |
||
395 | return $this->returnError(400, "Bad Request", "lang parameter missing"); |
||
396 | } |
||
397 | if ($this->notModified($request->getVocab())) { |
||
398 | return null; |
||
399 | } |
||
400 | |||
401 | $this->setLanguageProperties($request->getLang()); |
||
402 | |||
403 | $queriedtypes = $this->model->getTypes($vocid, $request->getLang()); |
||
404 | |||
405 | $types = array(); |
||
406 | |||
407 | /* encode the results in a JSON-LD compatible array */ |
||
408 | foreach ($queriedtypes as $uri => $typedata) { |
||
409 | $type = array_merge(array('uri' => $uri), $typedata); |
||
410 | $types[] = $type; |
||
411 | } |
||
412 | |||
413 | $base = $request->getVocab() ? $this->getBaseHref() . "rest/v1/" . $request->getVocab()->getId() . "/" : $this->getBaseHref() . "rest/v1/"; |
||
414 | |||
415 | $ret = array_merge_recursive($this->context, array( |
||
416 | '@context' => array( |
||
417 | 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#', |
||
418 | 'onki' => 'http://schema.onki.fi/onki#', |
||
419 | 'label' => 'rdfs:label', |
||
420 | 'superclass' => array('@id' => 'rdfs:subClassOf', '@type' => '@id'), |
||
421 | 'types' => 'onki:hasType', |
||
422 | '@language' => $request->getLang(), |
||
423 | '@base' => $base, |
||
424 | ), |
||
425 | 'uri' => '', |
||
426 | 'types' => $types) |
||
427 | ); |
||
428 | |||
429 | return $this->returnJson($ret); |
||
430 | } |
||
431 | |||
432 | private function findLookupHits($results, $label, $lang) |
||
433 | { |
||
434 | $hits = array(); |
||
435 | // case 1: exact match on preferred label |
||
436 | foreach ($results as $res) { |
||
437 | if (isset($res['prefLabel']) && $res['prefLabel'] == $label) { |
||
438 | $hits[] = $res; |
||
439 | } |
||
440 | } |
||
441 | if (sizeof($hits) > 0) return $hits; |
||
442 | |||
443 | // case 2: case-insensitive match on preferred label |
||
444 | foreach ($results as $res) { |
||
445 | if (isset($res['prefLabel']) && strtolower($res['prefLabel']) == strtolower($label)) { |
||
446 | $hits[] = $res; |
||
447 | } |
||
448 | } |
||
449 | if (sizeof($hits) > 0) return $hits; |
||
450 | |||
451 | if ($lang === null) { |
||
452 | // case 1A: exact match on preferred label in any language |
||
453 | foreach ($results as $res) { |
||
454 | if (isset($res['matchedPrefLabel']) && $res['matchedPrefLabel'] == $label) { |
||
455 | $res['prefLabel'] = $res['matchedPrefLabel']; |
||
456 | unset($res['matchedPrefLabel']); |
||
457 | $hits[] = $res; |
||
458 | } |
||
459 | } |
||
460 | if (sizeof($hits) > 0) return $hits; |
||
461 | |||
462 | // case 2A: case-insensitive match on preferred label in any language |
||
463 | foreach ($results as $res) { |
||
464 | if (isset($res['matchedPrefLabel']) && strtolower($res['matchedPrefLabel']) == strtolower($label)) { |
||
465 | $res['prefLabel'] = $res['matchedPrefLabel']; |
||
466 | unset($res['matchedPrefLabel']); |
||
467 | $hits[] = $res; |
||
468 | } |
||
469 | } |
||
470 | if (sizeof($hits) > 0) return $hits; |
||
471 | } |
||
472 | |||
473 | // case 3: exact match on alternate label |
||
474 | foreach ($results as $res) { |
||
475 | if (isset($res['altLabel']) && $res['altLabel'] == $label) { |
||
476 | $hits[] = $res; |
||
477 | } |
||
478 | } |
||
479 | if (sizeof($hits) > 0) return $hits; |
||
480 | |||
481 | |||
482 | // case 4: case-insensitive match on alternate label |
||
483 | foreach ($results as $res) { |
||
484 | if (isset($res['altLabel']) && strtolower($res['altLabel']) == strtolower($label)) { |
||
485 | $hits[] = $res; |
||
486 | } |
||
487 | } |
||
488 | if (sizeof($hits) > 0) return $hits; |
||
489 | |||
490 | return $hits; |
||
491 | } |
||
492 | |||
493 | private function transformLookupResults($lang, $hits) |
||
494 | { |
||
495 | if (sizeof($hits) == 0) { |
||
496 | // no matches found |
||
497 | return; |
||
498 | } |
||
499 | |||
500 | // found matches, getting rid of Vocabulary objects |
||
501 | foreach ($hits as &$res) { |
||
502 | unset($res['voc']); |
||
503 | } |
||
504 | |||
505 | $ret = array_merge_recursive($this->context, array( |
||
506 | '@context' => array('onki' => 'http://schema.onki.fi/onki#', 'results' => array('@id' => 'onki:results'), 'prefLabel' => 'skos:prefLabel', 'altLabel' => 'skos:altLabel', 'hiddenLabel' => 'skos:hiddenLabel'), |
||
507 | 'result' => $hits) |
||
508 | ); |
||
509 | |||
510 | if ($lang) { |
||
511 | $ret['@context']['@language'] = $lang; |
||
512 | } |
||
513 | |||
514 | return $ret; |
||
515 | } |
||
516 | |||
517 | /** |
||
518 | * Used for finding terms by their exact prefLabel. Wraps the result in a json-ld object. |
||
519 | * @param Request $request |
||
520 | */ |
||
521 | public function lookup($request) |
||
522 | { |
||
523 | $label = $request->getQueryParamRaw('label'); |
||
524 | if (!$label) { |
||
525 | return $this->returnError(400, "Bad Request", "label parameter missing"); |
||
526 | } |
||
527 | |||
528 | $lang = $request->getQueryParam('lang'); |
||
529 | $parameters = new ConceptSearchParameters($request, $this->model->getConfig(), true); |
||
530 | $results = $this->model->searchConcepts($parameters); |
||
531 | $hits = $this->findLookupHits($results, $label, $lang); |
||
532 | $ret = $this->transformLookupResults($lang, $hits); |
||
533 | if ($ret === null) { |
||
534 | return $this->returnError(404, 'Not Found', "Could not find label '$label'"); |
||
535 | } |
||
536 | return $this->returnJson($ret); |
||
537 | } |
||
538 | |||
539 | /** |
||
540 | * Queries the top concepts of a vocabulary and wraps the results in a json-ld object. |
||
541 | * @param Request $request |
||
542 | * @return object json-ld object |
||
543 | */ |
||
544 | public function topConcepts($request) |
||
545 | { |
||
546 | $vocab = $request->getVocab(); |
||
547 | if ($this->notModified($vocab)) { |
||
548 | return null; |
||
549 | } |
||
550 | $scheme = $request->getQueryParam('scheme'); |
||
551 | if (!$scheme) { |
||
552 | $scheme = $vocab->getConfig()->showConceptSchemesInHierarchy() ? array_keys($vocab->getConceptSchemes()) : $vocab->getDefaultConceptScheme(); |
||
553 | } |
||
554 | |||
555 | /* encode the results in a JSON-LD compatible array */ |
||
556 | $topconcepts = $vocab->getTopConcepts($scheme, $request->getLang()); |
||
557 | |||
558 | $ret = array_merge_recursive($this->context, array( |
||
559 | '@context' => array('onki' => 'http://schema.onki.fi/onki#', 'topconcepts' => 'skos:hasTopConcept', 'notation' => 'skos:notation', 'label' => 'skos:prefLabel', '@language' => $request->getLang()), |
||
560 | 'uri' => $scheme, |
||
561 | 'topconcepts' => $topconcepts) |
||
562 | ); |
||
563 | |||
564 | return $this->returnJson($ret); |
||
565 | } |
||
566 | |||
567 | private function redirectToVocabData($request) { |
||
568 | $urls = $request->getVocab()->getConfig()->getDataURLs(); |
||
569 | if (sizeof($urls) == 0) { |
||
570 | $vocid = $request->getVocab()->getId(); |
||
571 | return $this->returnError('404', 'Not Found', "No download source URL known for vocabulary $vocid"); |
||
572 | } |
||
573 | |||
574 | $format = $this->negotiateFormat(array_keys($urls), $request->getServerConstant('HTTP_ACCEPT'), $request->getQueryParam('format')); |
||
575 | if (!$format) { |
||
576 | return $this->returnError(406, 'Not Acceptable', "Unsupported format. Supported MIME types are: " . implode(' ', array_keys($urls))); |
||
577 | } |
||
578 | if (is_array($urls[$format])) { |
||
579 | $arr = $urls[$format]; |
||
580 | $dataLang = $request->getLang(); |
||
581 | if (isset($arr[$dataLang])) { |
||
582 | header("Location: " . $arr[$dataLang]); |
||
583 | } else { |
||
584 | $vocid = $request->getVocab()->getId(); |
||
585 | return $this->returnError('404', 'Not Found', "No download source URL known for vocabulary $vocid in language $dataLang"); |
||
586 | } |
||
587 | } else { |
||
588 | header("Location: " . $urls[$format]); |
||
589 | } |
||
590 | } |
||
591 | |||
592 | private function returnDataResults($results, $format) { |
||
593 | if ($format == 'application/ld+json' || $format == 'application/json') { |
||
594 | // further compact JSON-LD document using a context |
||
595 | $context = array( |
||
596 | 'skos' => 'http://www.w3.org/2004/02/skos/core#', |
||
597 | 'isothes' => 'http://purl.org/iso25964/skos-thes#', |
||
598 | 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#', |
||
599 | 'owl' => 'http://www.w3.org/2002/07/owl#', |
||
600 | 'dct' => 'http://purl.org/dc/terms/', |
||
601 | 'dc11' => 'http://purl.org/dc/elements/1.1/', |
||
602 | 'uri' => '@id', |
||
603 | 'type' => '@type', |
||
604 | 'lang' => '@language', |
||
605 | 'value' => '@value', |
||
606 | 'graph' => '@graph', |
||
607 | 'label' => 'rdfs:label', |
||
608 | 'prefLabel' => 'skos:prefLabel', |
||
609 | 'altLabel' => 'skos:altLabel', |
||
610 | 'hiddenLabel' => 'skos:hiddenLabel', |
||
611 | 'broader' => 'skos:broader', |
||
612 | 'narrower' => 'skos:narrower', |
||
613 | 'related' => 'skos:related', |
||
614 | 'inScheme' => 'skos:inScheme', |
||
615 | 'exactMatch' => 'skos:exactMatch', |
||
616 | 'closeMatch' => 'skos:closeMatch', |
||
617 | 'broadMatch' => 'skos:broadMatch', |
||
618 | 'narrowMatch' => 'skos:narrowMatch', |
||
619 | 'relatedMatch' => 'skos:relatedMatch', |
||
620 | ); |
||
621 | $compactJsonLD = \ML\JsonLD\JsonLD::compact($results, json_encode($context)); |
||
622 | $results = \ML\JsonLD\JsonLD::toString($compactJsonLD); |
||
623 | } |
||
624 | |||
625 | header("Content-type: $format; charset=utf-8"); |
||
626 | echo $results; |
||
627 | } |
||
628 | |||
629 | /** |
||
630 | * Download a concept as json-ld or redirect to download the whole vocabulary. |
||
631 | * @param Request $request |
||
632 | * @return object json-ld formatted concept. |
||
633 | */ |
||
634 | public function data($request) |
||
635 | { |
||
636 | $vocab = $request->getVocab(); |
||
637 | if ($this->notModified($request->getVocab())) { |
||
638 | return null; |
||
639 | } |
||
640 | |||
641 | if ($request->getUri()) { |
||
642 | $uri = $request->getUri(); |
||
643 | } else if ($vocab !== null) { // whole vocabulary - redirect to download URL |
||
644 | return $this->redirectToVocabData($request); |
||
645 | } else { |
||
646 | return $this->returnError(400, 'Bad Request', "uri parameter missing"); |
||
647 | } |
||
648 | |||
649 | $format = $this->negotiateFormat(explode(' ', self::SUPPORTED_FORMATS), $request->getServerConstant('HTTP_ACCEPT'), $request->getQueryParam('format')); |
||
650 | if (!$format) { |
||
651 | return $this->returnError(406, 'Not Acceptable', "Unsupported format. Supported MIME types are: " . self::SUPPORTED_FORMATS); |
||
652 | } |
||
653 | |||
654 | $vocid = $vocab ? $vocab->getId() : null; |
||
655 | $results = $this->model->getRDF($vocid, $uri, $format); |
||
656 | if (empty($results)) { |
||
657 | return $this->returnError(404, 'Bad Request', "no concept found with given uri"); |
||
658 | } |
||
659 | return $this->returnDataResults($results, $format); |
||
660 | } |
||
661 | |||
662 | /** |
||
663 | * Get the mappings associated with a concept, enriched with labels and notations. |
||
664 | * Returns a JSKOS-compatible JSON object. |
||
665 | * @param Request $request |
||
666 | * @throws Exception if the vocabulary ID is not found in configuration |
||
667 | */ |
||
668 | public function mappings(Request $request) |
||
669 | { |
||
670 | $this->setLanguageProperties($request->getLang()); |
||
671 | $vocab = $request->getVocab(); |
||
672 | if ($this->notModified($vocab)) { |
||
673 | return null; |
||
674 | } |
||
675 | |||
676 | $uri = $request->getUri(); |
||
677 | if (!$uri) { |
||
678 | return $this->returnError(400, 'Bad Request', "uri parameter missing"); |
||
0 ignored issues
–
show
|
|||
679 | } |
||
680 | |||
681 | $queryExVocabs = $request->getQueryParamBoolean('external', true); |
||
682 | |||
683 | $results = $vocab->getConceptInfo($uri, $request->getContentLang()); |
||
684 | if (empty($results)) { |
||
685 | return $this->returnError(404, 'Bad Request', "no concept found with given uri"); |
||
0 ignored issues
–
show
Are you sure the usage of
$this->returnError(404, ... found with given uri') targeting Controller::returnError() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
686 | } |
||
687 | |||
688 | $concept = $results[0]; |
||
689 | |||
690 | $mappings = []; |
||
691 | foreach ($concept->getMappingProperties() as $mappingProperty) { |
||
692 | foreach ($mappingProperty->getValues() as $mappingPropertyValue) { |
||
693 | $hrefLink = $this->linkUrlFilter($mappingPropertyValue->getUri(), $mappingPropertyValue->getExVocab(), $request->getLang(), 'page', $request->getContentLang()); |
||
694 | $mappings[] = $mappingPropertyValue->asJskos($queryExVocabs, $request->getLang(), $hrefLink); |
||
695 | } |
||
696 | } |
||
697 | |||
698 | $ret = array( |
||
699 | 'mappings' => $mappings, |
||
700 | 'graph' => $concept->dumpJsonLd() |
||
701 | ); |
||
702 | |||
703 | return $this->returnJson($ret); |
||
704 | } |
||
705 | |||
706 | /** |
||
707 | * Used for querying labels for a uri. |
||
708 | * @param Request $request |
||
709 | * @return object json-ld wrapped labels. |
||
710 | */ |
||
711 | public function label($request) |
||
712 | { |
||
713 | if (!$request->getUri()) { |
||
714 | return $this->returnError(400, "Bad Request", "uri parameter missing"); |
||
715 | } |
||
716 | |||
717 | if ($this->notModified($request->getVocab())) { |
||
718 | return null; |
||
719 | } |
||
720 | |||
721 | $vocab = $request->getVocab(); |
||
722 | if ($vocab === null) { |
||
723 | $vocab = $this->model->guessVocabularyFromUri($request->getUri()); |
||
724 | } |
||
725 | if ($vocab === null) { |
||
726 | return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>"); |
||
727 | } |
||
728 | |||
729 | $labelResults = $vocab->getAllConceptLabels($request->getUri(), $request->getLang()); |
||
730 | if ($labelResults === null) { |
||
731 | return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>"); |
||
732 | } |
||
733 | |||
734 | // there should be only one preferred label so no need for an array |
||
735 | if (array_key_exists('prefLabel', $labelResults)) { |
||
736 | $labelResults['prefLabel'] = $labelResults['prefLabel'][0]; |
||
737 | } |
||
738 | |||
739 | $ret = array_merge_recursive($this->context, |
||
740 | array('@context' => array('prefLabel' => 'skos:prefLabel', 'altLabel' => 'skos:altLabel', 'hiddenLabel' => 'skos:hiddenLabel', '@language' => $request->getLang()), |
||
741 | 'uri' => $request->getUri()), |
||
742 | $labelResults); |
||
743 | |||
744 | return $this->returnJson($ret); |
||
745 | } |
||
746 | |||
747 | /** |
||
748 | * Query for the available letters in the alphabetical index. |
||
749 | * @param Request $request |
||
750 | * @return object JSON-LD wrapped list of letters |
||
751 | */ |
||
752 | |||
753 | public function indexLetters($request) |
||
754 | { |
||
755 | $this->setLanguageProperties($request->getLang()); |
||
756 | $letters = $request->getVocab()->getAlphabet($request->getLang()); |
||
757 | |||
758 | $ret = array_merge_recursive($this->context, array( |
||
759 | '@context' => array( |
||
760 | 'indexLetters' => array( |
||
761 | '@id' => 'skosmos:indexLetters', |
||
762 | '@container' => '@list', |
||
763 | '@language' => $request->getLang() |
||
764 | ) |
||
765 | ), |
||
766 | 'uri' => '', |
||
767 | 'indexLetters' => $letters) |
||
768 | ); |
||
769 | return $this->returnJson($ret); |
||
770 | } |
||
771 | |||
772 | /** |
||
773 | * Query for the concepts with terms starting with a given letter in the |
||
774 | * alphabetical index. |
||
775 | * @param Request $request |
||
776 | * @return object JSON-LD wrapped list of terms/concepts |
||
777 | */ |
||
778 | |||
779 | public function indexConcepts($letter, $request) |
||
780 | { |
||
781 | $this->setLanguageProperties($request->getLang()); |
||
782 | |||
783 | $offset_param = $request->getQueryParam('offset'); |
||
784 | $offset = (is_numeric($offset_param) && $offset_param >= 0) ? $offset_param : 0; |
||
785 | $limit_param = $request->getQueryParam('limit'); |
||
786 | $limit = (is_numeric($limit_param) && $limit_param >= 0) ? $limit_param : 0; |
||
787 | |||
788 | $concepts = $request->getVocab()->searchConceptsAlphabetical($letter, $limit, $offset, $request->getLang()); |
||
789 | |||
790 | $ret = array_merge_recursive($this->context, array( |
||
791 | '@context' => array( |
||
792 | 'indexConcepts' => array( |
||
793 | '@id' => 'skosmos:indexConcepts', |
||
794 | '@container' => '@list' |
||
795 | ) |
||
796 | ), |
||
797 | 'uri' => '', |
||
798 | 'indexConcepts' => $concepts) |
||
799 | ); |
||
800 | return $this->returnJson($ret); |
||
801 | } |
||
802 | |||
803 | private function transformPropertyResults($uri, $lang, $objects, $propname, $propuri) |
||
804 | { |
||
805 | $results = array(); |
||
806 | foreach ($objects as $objuri => $vals) { |
||
807 | $results[] = array('uri' => $objuri, 'prefLabel' => $vals['label']); |
||
808 | } |
||
809 | |||
810 | return array_merge_recursive($this->context, array( |
||
811 | '@context' => array('prefLabel' => 'skos:prefLabel', $propname => $propuri, '@language' => $lang), |
||
812 | 'uri' => $uri, |
||
813 | $propname => $results) |
||
814 | ); |
||
815 | } |
||
816 | |||
817 | private function transformTransitivePropertyResults($uri, $lang, $objects, $tpropname, $tpropuri, $dpropname, $dpropuri) |
||
818 | { |
||
819 | $results = array(); |
||
820 | foreach ($objects as $objuri => $vals) { |
||
821 | $result = array('uri' => $objuri, 'prefLabel' => $vals['label']); |
||
822 | if (isset($vals['direct'])) { |
||
823 | $result[$dpropname] = $vals['direct']; |
||
824 | } |
||
825 | $results[$objuri] = $result; |
||
826 | } |
||
827 | |||
828 | return array_merge_recursive($this->context, array( |
||
829 | '@context' => array('prefLabel' => 'skos:prefLabel', $dpropname => array('@id' => $dpropuri, '@type' => '@id'), $tpropname => array('@id' => $tpropuri, '@container' => '@index'), '@language' => $lang), |
||
830 | 'uri' => $uri, |
||
831 | $tpropname => $results) |
||
832 | ); |
||
833 | } |
||
834 | |||
835 | /** |
||
836 | * Used for querying broader relations for a concept. |
||
837 | * @param Request $request |
||
838 | * @return object json-ld wrapped broader concept uris and labels. |
||
839 | */ |
||
840 | public function broader($request) |
||
841 | { |
||
842 | if ($this->notModified($request->getVocab())) { |
||
843 | return null; |
||
844 | } |
||
845 | $broaders = $request->getVocab()->getConceptBroaders($request->getUri(), $request->getLang()); |
||
846 | if ($broaders === null) { |
||
847 | return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>"); |
||
848 | } |
||
849 | $ret = $this->transformPropertyResults($request->getUri(), $request->getLang(), $broaders, "broader", "skos:broader"); |
||
850 | return $this->returnJson($ret); |
||
851 | } |
||
852 | |||
853 | /** |
||
854 | * Used for querying broader transitive relations for a concept. |
||
855 | * @param Request $request |
||
856 | * @return object json-ld wrapped broader transitive concept uris and labels. |
||
857 | */ |
||
858 | public function broaderTransitive($request) |
||
859 | { |
||
860 | if ($this->notModified($request->getVocab())) { |
||
861 | return null; |
||
862 | } |
||
863 | $broaders = $request->getVocab()->getConceptTransitiveBroaders($request->getUri(), $this->parseLimit(), false, $request->getLang()); |
||
864 | if (empty($broaders)) { |
||
865 | return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>"); |
||
866 | } |
||
867 | $ret = $this->transformTransitivePropertyResults($request->getUri(), $request->getLang(), $broaders, "broaderTransitive", "skos:broaderTransitive", "broader", "skos:broader"); |
||
868 | return $this->returnJson($ret); |
||
869 | } |
||
870 | |||
871 | /** |
||
872 | * Used for querying narrower relations for a concept. |
||
873 | * @param Request $request |
||
874 | * @return object json-ld wrapped narrower concept uris and labels. |
||
875 | */ |
||
876 | public function narrower($request) |
||
877 | { |
||
878 | if ($this->notModified($request->getVocab())) { |
||
879 | return null; |
||
880 | } |
||
881 | $narrowers = $request->getVocab()->getConceptNarrowers($request->getUri(), $request->getLang()); |
||
882 | if ($narrowers === null) { |
||
883 | return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>"); |
||
884 | } |
||
885 | $ret = $this->transformPropertyResults($request->getUri(), $request->getLang(), $narrowers, "narrower", "skos:narrower"); |
||
886 | return $this->returnJson($ret); |
||
887 | } |
||
888 | |||
889 | /** |
||
890 | * Used for querying narrower transitive relations for a concept. |
||
891 | * @param Request $request |
||
892 | * @return object json-ld wrapped narrower transitive concept uris and labels. |
||
893 | */ |
||
894 | public function narrowerTransitive($request) |
||
895 | { |
||
896 | if ($this->notModified($request->getVocab())) { |
||
897 | return null; |
||
898 | } |
||
899 | $narrowers = $request->getVocab()->getConceptTransitiveNarrowers($request->getUri(), $this->parseLimit(), $request->getLang()); |
||
900 | if (empty($narrowers)) { |
||
901 | return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>"); |
||
902 | } |
||
903 | $ret = $this->transformTransitivePropertyResults($request->getUri(), $request->getLang(), $narrowers, "narrowerTransitive", "skos:narrowerTransitive", "narrower", "skos:narrower"); |
||
904 | return $this->returnJson($ret); |
||
905 | } |
||
906 | |||
907 | /** |
||
908 | * Used for querying broader transitive relations |
||
909 | * and some narrowers for a concept in the hierarchy view. |
||
910 | * @param Request $request |
||
911 | * @return object json-ld wrapped hierarchical concept uris and labels. |
||
912 | */ |
||
913 | public function hierarchy($request) |
||
914 | { |
||
915 | if ($this->notModified($request->getVocab())) { |
||
916 | return null; |
||
917 | } |
||
918 | $results = $request->getVocab()->getConceptHierarchy($request->getUri(), $request->getLang()); |
||
919 | if (empty($results)) { |
||
920 | return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>"); |
||
921 | } |
||
922 | |||
923 | // set the "top" key from the "tops" key |
||
924 | foreach ($results as $value) { |
||
925 | $uri = $value['uri']; |
||
926 | if (isset($value['tops'])) { |
||
927 | if ($request->getVocab()->getConfig()->getMainConceptSchemeURI() != null) { |
||
928 | foreach ($results[$uri]['tops'] as $top) { |
||
929 | // if a value in 'tops' matches the main concept scheme of the vocabulary, take it |
||
930 | if ($top == $request->getVocab()->getConfig()->getMainConceptSchemeURI()) { |
||
931 | $results[$uri]['top'] = $top; |
||
932 | break; |
||
933 | } |
||
934 | } |
||
935 | // if the main concept scheme was not found, set 'top' to the first 'tops' (sorted alphabetically on the URIs) |
||
936 | if (! isset($results[$uri]['top'])) { |
||
937 | $results[$uri]['top'] = $results[$uri]['tops'][0]; |
||
938 | } |
||
939 | } else { |
||
940 | // no main concept scheme set on the vocab, take the first value of 'tops' (sorted alphabetically) |
||
941 | $results[$uri]['top'] = $results[$uri]['tops'][0]; |
||
942 | } |
||
943 | } |
||
944 | } |
||
945 | |||
946 | if ($request->getVocab()->getConfig()->getShowHierarchy()) { |
||
947 | $schemes = $request->getVocab()->getConceptSchemes($request->getLang()); |
||
948 | foreach ($schemes as $scheme) { |
||
949 | if (!isset($scheme['title']) && !isset($scheme['label']) && !isset($scheme['prefLabel'])) { |
||
950 | unset($schemes[array_search($scheme, $schemes)]); |
||
951 | } |
||
952 | |||
953 | } |
||
954 | |||
955 | /* encode the results in a JSON-LD compatible array */ |
||
956 | $topconcepts = $request->getVocab()->getTopConcepts(array_keys($schemes), $request->getLang()); |
||
957 | foreach ($topconcepts as $top) { |
||
958 | if (!isset($results[$top['uri']])) { |
||
959 | $results[$top['uri']] = array('uri' => $top['uri'], 'top'=>$top['topConceptOf'], 'tops'=>array($top['topConceptOf']), 'prefLabel' => $top['label'], 'hasChildren' => $top['hasChildren']); |
||
960 | if (isset($top['notation'])) { |
||
961 | $results[$top['uri']]['notation'] = $top['notation']; |
||
962 | } |
||
963 | |||
964 | } |
||
965 | } |
||
966 | } |
||
967 | |||
968 | $ret = array_merge_recursive($this->context, array( |
||
969 | '@context' => array( |
||
970 | 'onki' => 'http://schema.onki.fi/onki#', |
||
971 | 'prefLabel' => 'skos:prefLabel', |
||
972 | 'notation' => 'skos:notation', |
||
973 | 'narrower' => array('@id' => 'skos:narrower', '@type' => '@id'), |
||
974 | 'broader' => array('@id' => 'skos:broader', '@type' => '@id'), |
||
975 | 'broaderTransitive' => array('@id' => 'skos:broaderTransitive', '@container' => '@index'), |
||
976 | 'top' => array('@id' => 'skos:topConceptOf', '@type' => '@id'), |
||
977 | // the tops key will contain all the concept scheme values, while top (singular) contains a single value |
||
978 | 'tops' => array('@id' => 'skos:topConceptOf', '@type' => '@id'), |
||
979 | 'hasChildren' => 'onki:hasChildren', |
||
980 | '@language' => $request->getLang() |
||
981 | ), |
||
982 | 'uri' => $request->getUri(), |
||
983 | 'broaderTransitive' => $results) |
||
984 | ); |
||
985 | |||
986 | return $this->returnJson($ret); |
||
987 | } |
||
988 | |||
989 | /** |
||
990 | * Used for querying group hierarchy for the sidebar group view. |
||
991 | * @param Request $request |
||
992 | * @return object json-ld wrapped hierarchical concept uris and labels. |
||
993 | */ |
||
994 | public function groups($request) |
||
995 | { |
||
996 | if ($this->notModified($request->getVocab())) { |
||
997 | return null; |
||
998 | } |
||
999 | $results = $request->getVocab()->listConceptGroups($request->getLang()); |
||
1000 | |||
1001 | $ret = array_merge_recursive($this->context, array( |
||
1002 | '@context' => array('onki' => 'http://schema.onki.fi/onki#', 'prefLabel' => 'skos:prefLabel', 'groups' => 'onki:hasGroup', 'childGroups' => array('@id' => 'skos:member', '@type' => '@id'), 'hasMembers' => 'onki:hasMembers', '@language' => $request->getLang()), |
||
1003 | 'uri' => '', |
||
1004 | 'groups' => $results) |
||
1005 | ); |
||
1006 | |||
1007 | return $this->returnJson($ret); |
||
1008 | } |
||
1009 | |||
1010 | /** |
||
1011 | * Used for querying member relations for a group. |
||
1012 | * @param Request $request |
||
1013 | * @return object json-ld wrapped narrower concept uris and labels. |
||
1014 | */ |
||
1015 | public function groupMembers($request) |
||
1016 | { |
||
1017 | if ($this->notModified($request->getVocab())) { |
||
1018 | return null; |
||
1019 | } |
||
1020 | $children = $request->getVocab()->listConceptGroupContents($request->getUri(), $request->getLang()); |
||
1021 | if (empty($children)) { |
||
1022 | return $this->returnError('404', 'Not Found', "Could not find group <{$request->getUri()}>"); |
||
1023 | } |
||
1024 | |||
1025 | $ret = array_merge_recursive($this->context, array( |
||
1026 | '@context' => array('prefLabel' => 'skos:prefLabel', 'members' => 'skos:member', '@language' => $request->getLang()), |
||
1027 | 'uri' => $request->getUri(), |
||
1028 | 'members' => $children) |
||
1029 | ); |
||
1030 | |||
1031 | return $this->returnJson($ret); |
||
0 ignored issues
–
show
Are you sure the usage of
$this->returnJson($ret) targeting RestController::returnJson() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
1032 | } |
||
1033 | |||
1034 | /** |
||
1035 | * Used for querying narrower relations for a concept in the hierarchy view. |
||
1036 | * @param Request $request |
||
1037 | * @return object json-ld wrapped narrower concept uris and labels. |
||
1038 | */ |
||
1039 | public function children($request) |
||
1040 | { |
||
1041 | if ($this->notModified($request->getVocab())) { |
||
1042 | return null; |
||
1043 | } |
||
1044 | $children = $request->getVocab()->getConceptChildren($request->getUri(), $request->getLang()); |
||
1045 | if ($children === null) { |
||
1046 | return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>"); |
||
1047 | } |
||
1048 | |||
1049 | $ret = array_merge_recursive($this->context, array( |
||
1050 | '@context' => array('prefLabel' => 'skos:prefLabel', 'narrower' => 'skos:narrower', 'notation' => 'skos:notation', 'hasChildren' => 'onki:hasChildren', '@language' => $request->getLang()), |
||
1051 | 'uri' => $request->getUri(), |
||
1052 | 'narrower' => $children) |
||
1053 | ); |
||
1054 | |||
1055 | return $this->returnJson($ret); |
||
1056 | } |
||
1057 | |||
1058 | /** |
||
1059 | * Used for querying narrower relations for a concept in the hierarchy view. |
||
1060 | * @param Request $request |
||
1061 | * @return object json-ld wrapped hierarchical concept uris and labels. |
||
1062 | */ |
||
1063 | public function related($request) |
||
1064 | { |
||
1065 | if ($this->notModified($request->getVocab())) { |
||
1066 | return null; |
||
1067 | } |
||
1068 | $related = $request->getVocab()->getConceptRelateds($request->getUri(), $request->getLang()); |
||
1069 | if ($related === null) { |
||
1070 | return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>"); |
||
1071 | } |
||
1072 | $ret = $this->transformPropertyResults($request->getUri(), $request->getLang(), $related, "related", "skos:related"); |
||
1073 | return $this->returnJson($ret); |
||
1074 | } |
||
1075 | |||
1076 | /** |
||
1077 | * Used for querying new concepts in the vocabulary |
||
1078 | * @param Request $request |
||
1079 | * @return object json-ld wrapped list of changed concepts |
||
1080 | */ |
||
1081 | public function newConcepts($request) |
||
1082 | { |
||
1083 | $offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0; |
||
1084 | $limit = ($request->getQueryParam('limit') && is_numeric($request->getQueryParam('limit')) && $request->getQueryParam('limit') >= 0) ? $request->getQueryParam('limit') : 200; |
||
1085 | |||
1086 | return $this->changedConcepts($request, 'dc:created', $offset, $limit); |
||
1087 | } |
||
1088 | |||
1089 | /** |
||
1090 | * Used for querying modified concepts in the vocabulary |
||
1091 | * @param Request $request |
||
1092 | * @return object json-ld wrapped list of changed concepts |
||
1093 | */ |
||
1094 | public function modifiedConcepts($request) |
||
1095 | { |
||
1096 | $offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0; |
||
1097 | $limit = ($request->getQueryParam('limit') && is_numeric($request->getQueryParam('limit')) && $request->getQueryParam('limit') >= 0) ? $request->getQueryParam('limit') : 200; |
||
1098 | |||
1099 | return $this->changedConcepts($request, 'dc:modified', $offset, $limit); |
||
1100 | } |
||
1101 | |||
1102 | /** |
||
1103 | * Used for querying changed concepts in the vocabulary |
||
1104 | * @param Request $request |
||
1105 | * @param int $offset starting index offset |
||
1106 | * @param int $limit maximum number of concepts to return |
||
1107 | * @return object json-ld wrapped list of changed concepts |
||
1108 | */ |
||
1109 | private function changedConcepts($request, $prop, $offset, $limit) |
||
1110 | { |
||
1111 | $changeList = $request->getVocab()->getChangeList($prop, $request->getLang(), $offset, $limit); |
||
1112 | |||
1113 | $simpleChangeList = array(); |
||
1114 | foreach($changeList as $conceptInfo) { |
||
1115 | if (array_key_exists('date', $conceptInfo)) { |
||
1116 | $concept = array( |
||
1117 | 'uri' => $conceptInfo['uri'], |
||
1118 | 'prefLabel' => $conceptInfo['prefLabel'], |
||
1119 | 'date' => $conceptInfo['date']->format("Y-m-d\TH:i:sO") ); |
||
1120 | if (array_key_exists('replacedBy', $conceptInfo)) { |
||
1121 | $concept['replacedBy'] = $conceptInfo['replacedBy']; |
||
1122 | if (array_key_exists('replacingLabel', $conceptInfo)) { |
||
1123 | $concept['replacingLabel'] = $conceptInfo['replacingLabel']; |
||
1124 | } |
||
1125 | } |
||
1126 | $simpleChangeList[] = $concept; |
||
1127 | } |
||
1128 | } |
||
1129 | return $this->returnJson(array_merge_recursive($this->context, |
||
1130 | array('@context' => array( '@language' => $request->getLang(), |
||
1131 | 'prefLabel' => 'skos:prefLabel', |
||
1132 | 'xsd' => 'http://www.w3.org/2001/XMLSchema#', |
||
1133 | 'date' => array( '@id' => 'http://purl.org/dc/terms/date', '@type' => 'http://www.w3.org/2001/XMLSchema#dateTime') ) |
||
1134 | ), |
||
1135 | array('changeList' => $simpleChangeList))); |
||
1136 | |||
1137 | } |
||
1138 | } |
||
1139 |
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.