Total Complexity | 198 |
Total Lines | 1130 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like RestController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use RestController, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
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) |
||
113 | } |
||
114 | |||
115 | private function transformSearchResults($request, $results, $parameters) |
||
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 |
||
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"); |
||
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"); |
||
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) |
||
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) |
||
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); |
||
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) |
||
1136 | |||
1137 | } |
||
1138 | } |
||
1139 |