Completed
Push — master ( 0807cd...8d8c90 )
by Henri
03:22
created

RestController::vocabularyStatistics()   C

Complexity

Conditions 8
Paths 18

Size

Total Lines 63
Code Lines 48

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 63
rs 6.8825
cc 8
eloc 48
nc 18
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Copyright (c) 2012-2013 Aalto University and University of Helsinki
4
 * MIT License
5
 * see LICENSE.txt for more information
6
 */
7
8
/**
9
 * RestController is responsible for handling all the requests directed to the /rest address.
10
 */
11
class RestController extends Controller
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
12
{
13
    /* supported MIME types that can be used to return RDF data */
14
    const SUPPORTED_FORMATS = 'application/rdf+xml text/turtle application/ld+json application/json';
15
    /* context array template */
16
    private $context = array(
17
        '@context' => array(
18
            'skos' => 'http://www.w3.org/2004/02/skos/core#',
19
            'uri' => '@id',
20
            'type' => '@type',
21
        ),
22
    );
23
24
    /**
25
     * Handles json encoding, adding the content type headers and optional callback function.
26
     * @param array $data the data to be returned.
27
     */
28
    private function returnJson($data)
29
    {
30
        // wrap with JSONP callback if requested
31
        if (filter_input(INPUT_GET, 'callback', FILTER_SANITIZE_STRING)) {
32
            header("Content-type: application/javascript; charset=utf-8");
33
            echo filter_input(INPUT_GET, 'callback', FILTER_UNSAFE_RAW) . "(" . json_encode($data) . ");";
34
            return;
35
        }
36
        
37
        // otherwise negotiate suitable format for the response and return that
38
        $negotiator = new \Negotiation\FormatNegotiator();
39
        $priorities = array('application/json', 'application/ld+json');
40
        $best = filter_input(INPUT_SERVER, 'HTTP_ACCEPT', FILTER_SANITIZE_STRING) ? $negotiator->getBest(filter_input(INPUT_SERVER, 'HTTP_ACCEPT', FILTER_SANITIZE_STRING), $priorities) : null;
41
        $format = ($best !== null) ? $best->getValue() : $priorities[0];
42
        header("Content-type: $format; charset=utf-8");
43
        header("Vary: Accept"); // inform caches that we made a choice based on Accept header
44
        echo json_encode($data);
45
    }
46
47
    /**
48
     * Parses and returns the limit parameter. Returns and error if the parameter is missing.
49
     */
50
    private function parseLimit()
51
    {
52
        $limit = filter_input(INPUT_GET, 'limit', FILTER_SANITIZE_NUMBER_INT) ? filter_input(INPUT_GET, 'limit', FILTER_SANITIZE_NUMBER_INT) : $this->model->getConfig()->getDefaultTransitiveLimit();
53
        if ($limit <= 0) {
54
            return $this->returnError(400, "Bad Request", "Invalid limit parameter");
55
        }
56
57
        return $limit;
58
    }
59
60
61
/** Global REST methods **/
62
63
    /**
64
     * Returns all the vocabularies available on the server in a json object.
65
     */
66
    public function vocabularies($request)
67
    {
68
        if (!$request->getLang()) {
69
            return $this->returnError(400, "Bad Request", "lang parameter missing");
70
        }
71
72
        $this->setLanguageProperties($request->getLang());
73
74
        $vocabs = array();
75
        foreach ($this->model->getVocabularies() as $voc) {
76
            $vocabs[$voc->getId()] = $voc->getConfig()->getTitle($request->getLang());
77
        }
78
        ksort($vocabs);
79
        $results = array();
80
        foreach ($vocabs as $id => $title) {
81
            $results[] = array(
82
                'uri' => $id,
83
                'id' => $id,
84
                'title' => $title);
85
        }
86
87
        /* encode the results in a JSON-LD compatible array */
88
        $ret = array(
89
            '@context' => array(
90
                'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
91
                'onki' => 'http://schema.onki.fi/onki#',
92
                'title' => array('@id' => 'rdfs:label', '@language' => $request->getLang()),
93
                'vocabularies' => 'onki:hasVocabulary',
94
                'id' => 'onki:vocabularyIdentifier',
95
                'uri' => '@id',
96
            ),
97
            'uri' => '',
98
            'vocabularies' => $results,
99
        );
100
101
        return $this->returnJson($ret);
102
    }
103
    
104
    private function constructSearchParameters($request)
105
    {
106
        $parameters = new ConceptSearchParameters($request, $this->model->getConfig(), true);
107
        
108
        $vocabs = $request->getQueryParam('vocab'); # optional
109
        // convert to vocids array to support multi-vocabulary search
110
        $vocids = ($vocabs !== null && $vocabs !== '') ? explode(' ', $vocabs) : array();
111
        $vocabObjects = array();
112
        foreach($vocids as $vocid) {
113
            $vocabObjects[] = $this->model->getVocabulary($vocid);
114
        }
115
        $parameters->setVocabularies($vocabObjects);
116
        return $parameters;    
117
    }
118
119
    private function transformSearchResults($request, $results)
120
    {
121
        // before serializing to JSON, get rid of the Vocabulary object that came with each resource
122
        foreach ($results as &$res) {
123
            unset($res['voc']);
124
        }
125
        $ret = array(
126
            '@context' => array(
127
                'skos' => 'http://www.w3.org/2004/02/skos/core#',
128
                'isothes' => 'http://purl.org/iso25964/skos-thes#',
129
                'onki' => 'http://schema.onki.fi/onki#',
130
                'uri' => '@id',
131
                'type' => '@type',
132
                'results' => array(
133
                    '@id' => 'onki:results',
134
                    '@container' => '@list',
135
                ),
136
                'prefLabel' => 'skos:prefLabel',
137
                'altLabel' => 'skos:altLabel',
138
                'hiddenLabel' => 'skos:hiddenLabel',
139
            ),
140
            'uri' => '',
141
            'results' => $results,
142
        );
143
        
144
        if (isset($results[0]['prefLabels'])) {
145
            $ret['@context']['prefLabels'] = array('@id' => 'skos:prefLabel', '@container' => '@language');
146
        }
147
148
        if ($request->getQueryParam('labellang')) {
149
            $ret['@context']['@language'] = $request->getQueryParam('labellang');
150
        } elseif ($request->getQueryParam('lang')) {
151
            $ret['@context']['@language'] = $request->getQueryParam('lang');;
152
        }
153
        return $ret;
154
    }
155
156
    /**
157
     * Performs the search function calls. And wraps the result in a json-ld object.
158
     * @param Request $request
159
     */
160
    public function search($request)
161
    {
162
        $maxhits = $request->getQueryParam('maxhits');
163
        $offset = $request->getQueryParam('offset');
164
        $term = $request->getQueryParam('query');
165
166
        if (!$term) {
167
            return $this->returnError(400, "Bad Request", "query parameter missing");
168
        }
169
        if ($maxhits && (!is_numeric($maxhits) || $maxhits <= 0)) {
170
            return $this->returnError(400, "Bad Request", "maxhits parameter is invalid");
171
        }
172
        if ($offset && (!is_numeric($offset) || $offset < 0)) {
173
            return $this->returnError(400, "Bad Request", "offset parameter is invalid");
174
        }
175
176
        $parameters = $this->constructSearchParameters($request);
177
        $results = $this->model->searchConcepts($parameters);
178
        $ret = $this->transformSearchResults($request, $results);
179
180
        return $this->returnJson($ret);
181
    }
182
183
/** Vocabulary-specific methods **/
184
185
    /**
186
     * Loads the vocabulary metadata. And wraps the result in a json-ld object.
187
     * @param Request $request
188
     */
189
    public function vocabularyInformation($request)
190
    {
191
        $vocab = $request->getVocab();
192
193
        /* encode the results in a JSON-LD compatible array */
194
        $conceptschemes = array();
195
        foreach ($vocab->getConceptSchemes($request->getLang()) as $uri => $csdata) {
196
            $csdata['uri'] = $uri;
197
            $csdata['type'] = 'skos:ConceptScheme';
198
            $conceptschemes[] = $csdata;
199
        }
200
201
        $ret = array(
202
            '@context' => array(
203
                'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
204
                'skos' => 'http://www.w3.org/2004/02/skos/core#',
205
                'onki' => 'http://schema.onki.fi/onki#',
206
                'dct' => 'http://purl.org/dc/terms/',
207
                'uri' => '@id',
208
                'type' => '@type',
209
                'title' => 'rdfs:label',
210
                'conceptschemes' => 'onki:hasConceptScheme',
211
                'id' => 'onki:vocabularyIdentifier',
212
                'defaultLanguage' => 'onki:defaultLanguage',
213
                'languages' => 'onki:language',
214
                'label' => 'rdfs:label',
215
                'prefLabel' => 'skos:prefLabel',
216
                'title' => 'dct:title',
217
                '@language' => $request->getLang(),
218
            ),
219
            'uri' => '',
220
            'id' => $vocab->getId(),
221
            'title' => $vocab->getConfig()->getTitle($request->getLang()),
222
            'defaultLanguage' => $vocab->getConfig()->getDefaultLanguage(),
223
            'languages' => $vocab->getConfig()->getLanguages(),
224
            'conceptschemes' => $conceptschemes,
225
        );
226
227
        return $this->returnJson($ret);
228
    }
229
230
    /**
231
     * Loads the vocabulary metadata. And wraps the result in a json-ld object.
232
     * @param Request $request
233
     */
234
    public function vocabularyStatistics($request)
235
    {
236
        $this->setLanguageProperties($request->getLang());
237
        $arrayClass = $request->getVocab()->getConfig()->getArrayClassURI(); 
238
        $groupClass = $request->getVocab()->getConfig()->getGroupClassURI(); 
239
        $vocabStats = $request->getVocab()->getStatistics($request->getQueryParam('lang'), $arrayClass, $groupClass);
240
        $types = array('http://www.w3.org/2004/02/skos/core#Concept', 'http://www.w3.org/2004/02/skos/core#Collection', $arrayClass, $groupClass);
241
        $subTypes = array();
242
        foreach ($vocabStats as $subtype) {
243
            if (!in_array($subtype['type'], $types)) {
244
                $subTypes[] = $subtype;
245
            }
246
        }
247
248
        /* encode the results in a JSON-LD compatible array */
249
        $ret = array(
250
            '@context' => array(
251
                'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
252
                'skos' => 'http://www.w3.org/2004/02/skos/core#',
253
                'void' => 'http://rdfs.org/ns/void#',
254
                'onki' => 'http://schema.onki.fi/onki#',
255
                'uri' => '@id',
256
                'id' => 'onki:vocabularyIdentifier',
257
                'concepts' => 'void:classPartition',
258
                'label' => 'rdfs:label',
259
                'class' => array('@id' => 'void:class', '@type' => '@id'),
260
                'subTypes' => array('@id' => 'void:class', '@type' => '@id'),
261
                'count' => 'void:entities',
262
                '@language' => $request->getLang(),
263
            ),
264
            'uri' => '',
265
            'id' => $request->getVocab()->getId(),
266
            'title' => $request->getVocab()->getConfig()->getTitle(),
267
            'concepts' => array(
268
                'class' => 'http://www.w3.org/2004/02/skos/core#Concept',
269
                'label' => gettext('skos:Concept'),
270
                'count' => $vocabStats['http://www.w3.org/2004/02/skos/core#Concept']['count'],
271
            ),
272
            'subTypes' => $subTypes,
273
        );
274
275
        if (isset($vocabStats['http://www.w3.org/2004/02/skos/core#Collection'])) {
276
            $ret['conceptGroups'] = array(
277
                'class' => 'http://www.w3.org/2004/02/skos/core#Collection',
278
                'label' => gettext('skos:Collection'),
279
                'count' => $vocabStats['http://www.w3.org/2004/02/skos/core#Collection']['count'],
280
            );
281
        } else if (isset($vocabStats[$groupClass])) {
282
            $ret['conceptGroups'] = array(
283
                'class' => $groupClass,
284
                'label' => isset($vocabStats[$groupClass]['label']) ? $vocabStats[$groupClass]['label'] : gettext(EasyRdf_Namespace::shorten($groupClass)),
285
                'count' => $vocabStats[$groupClass]['count'],
286
            );
287
        } else if (isset($vocabStats[$arrayClass])) {
288
            $ret['arrays'] = array(
289
                'class' => $arrayClass,
290
                'label' => isset($vocabStats[$arrayClass]['label']) ? $vocabStats[$arrayClass]['label'] : gettext(EasyRdf_Namespace::shorten($arrayClass)),
291
                'count' => $vocabStats[$arrayClass]['count'],
292
            );
293
        }
294
295
        return $this->returnJson($ret);
296
    }
297
298
    /**
299
     * Loads the vocabulary metadata. And wraps the result in a json-ld object.
300
     * @param Request $request
301
     */
302
    public function labelStatistics($request)
303
    {
304
        $lang = $request->getLang();
305
        $this->setLanguageProperties($request->getLang());
306
        $vocabStats = $request->getVocab()->getLabelStatistics();
307
308
        /* encode the results in a JSON-LD compatible array */
309
        $counts = array();
310
        foreach ($vocabStats['terms'] as $proplang => $properties) {
311
            $langdata = array('language' => $proplang);
312
            if ($lang) {
313
                $langdata['literal'] = Punic\Language::getName($proplang, $lang);
314
            }
315
316
            $langdata['properties'] = array();
317
            foreach ($properties as $prop => $value) {
318
                $langdata['properties'][] = array('property' => $prop, 'labels' => $value);
319
            }
320
            $counts[] = $langdata;
321
        }
322
323
        $ret = array(
324
            '@context' => array(
325
                'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
326
                'skos' => 'http://www.w3.org/2004/02/skos/core#',
327
                'void' => 'http://rdfs.org/ns/void#',
328
                'void-ext' => 'http://ldf.fi/void-ext#',
329
                'onki' => 'http://schema.onki.fi/onki#',
330
                'uri' => '@id',
331
                'id' => 'onki:vocabularyIdentifier',
332
                'languages' => 'void-ext:languagePartition',
333
                'language' => 'void-ext:language',
334
                'properties' => 'void:propertyPartition',
335
                'labels' => 'void:triples',
336
            ),
337
            'uri' => '',
338
            'id' => $request->getVocab()->getId(),
339
            'title' => $request->getVocab()->getConfig()->getTitle($lang),
340
            'languages' => $counts,
341
        );
342
343
        if ($lang) {
344
            $ret['@context']['literal'] = array('@id' => 'rdfs:label', '@language' => $lang);
345
        }
346
347
        return $this->returnJson($ret);
348
    }
349
350
    /**
351
     * Loads the vocabulary type metadata. And wraps the result in a json-ld object.
352
     * @param Request $request
353
     */
354
    public function types($request)
355
    {
356
        $vocid = $request->getVocab() ? $request->getVocab()->getId() : null;
357
        if ($vocid === null && !$request->getLang()) {
358
            return $this->returnError(400, "Bad Request", "lang parameter missing");
359
        }
360
        $this->setLanguageProperties($request->getLang());
361
        
362
        $queriedtypes = $this->model->getTypes($vocid, $request->getLang());
363
364
        $types = array();
365
366
        /* encode the results in a JSON-LD compatible array */
367
        foreach ($queriedtypes as $uri => $typedata) {
368
            $type = array_merge(array('uri' => $uri), $typedata);
369
            $types[] = $type;
370
        }
371
372
        $ret = array_merge_recursive($this->context, array(
373
            '@context' => array('rdfs' => 'http://www.w3.org/2000/01/rdf-schema#', 'onki' => 'http://schema.onki.fi/onki#', 'label' => 'rdfs:label', 'superclass' => array('@id' => 'rdfs:subClassOf', '@type' => '@id'), 'types' => 'onki:hasType', '@language' => $request->getLang()),
374
            'uri' => '',
375
            'types' => $types)
376
        );
377
378
        return $this->returnJson($ret);
379
    }
380
    
381
    private function findLookupHits($results, $label)
382
    {
383
        $hits = array();
384
        // case 1: exact match on preferred label
385
        foreach ($results as $res) {
386
            if ($res['prefLabel'] == $label) {
387
                $hits[] = $res;
388
            }
389
        }
390
        if (sizeof($hits) > 0) return $hits;
391
392
        // case 2: case-insensitive match on preferred label
393
        foreach ($results as $res) {
394
            if (strtolower($res['prefLabel']) == strtolower($label)) {
395
                $hits[] = $res;
396
            }
397
        }
398
        if (sizeof($hits) > 0) return $hits;
399
400
        // case 3: exact match on alternate label
401
        foreach ($results as $res) {
402
            if (isset($res['altLabel']) && $res['altLabel'] == $label) {
403
                $hits[] = $res;
404
            }
405
        }
406
        if (sizeof($hits) > 0) return $hits;
407
408
409
        // case 4: case-insensitive match on alternate label
410
        foreach ($results as $res) {
411
            if (isset($res['altLabel']) && strtolower($res['altLabel']) == strtolower($label)) {
412
                $hits[] = $res;
413
            }
414
        }
415
        return $hits;   
416
    }
417
    
418
    private function transformLookupResults($lang, $hits, $label)
419
    {
420
        if (sizeof($hits) == 0) {
421
            // no matches found
422
            return $this->returnError(404, 'Not Found', "Could not find label '$label'");
423
        }
424
425
        // did find some matches!
426
        // get rid of Vocabulary objects
427
        foreach ($hits as &$res) {
428
            unset($res['voc']);
429
        }
430
431
        $ret = array_merge_recursive($this->context, array(
432
            '@context' => array('onki' => 'http://schema.onki.fi/onki#', 'results' => array('@id' => 'onki:results'), 'prefLabel' => 'skos:prefLabel', 'altLabel' => 'skos:altLabel', 'hiddenLabel' => 'skos:hiddenLabel'),
433
            'result' => $hits)
434
        );
435
436
        if ($lang) {
437
            $ret['@context']['@language'] = $lang;
438
        }
439
440
        return $ret;  
441
    }
442
443
    /**
444
     * Used for finding terms by their exact prefLabel. Wraps the result in a json-ld object.
445
     * @param Request $request
446
     */
447
    public function lookup($request)
448
    {
449
        $label = $request->getQueryParam('label');
450
        if (!$label) {
451
            return $this->returnError(400, "Bad Request", "label parameter missing");
452
        }
453
454
        $lang = $request->getQueryParam('lang');
455
        $parameters = new ConceptSearchParameters($request, $this->model->getConfig(), true);
456
        $results = $this->model->searchConcepts($parameters);
457
        $hits = $this->findLookupHits($results, $label);
458
        $ret = $this->transformLookupResults($lang, $hits, $label);
459
        return $this->returnJson($ret);
0 ignored issues
show
Bug introduced by
It seems like $ret defined by $this->transformLookupRe...s($lang, $hits, $label) on line 458 can also be of type null; however, RestController::returnJson() does only seem to accept array, maybe add an additional type check?

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

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

    return array();
}

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

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

Loading history...
460
    }
461
462
    /**
463
     * Queries the top concepts of a vocabulary and wraps the results in a json-ld object.
464
     * @param Request $request
465
     * @return object json-ld object
466
     */
467
    public function topConcepts($request)
468
    {
469
        $vocab = $request->getVocab();
470
        $scheme = $request->getQueryParam('scheme');
471
        if (!$scheme) {
472
            $scheme = $vocab->getConfig()->showConceptSchemesInHierarchy() ? array_keys($vocab->getConceptSchemes()) : $vocab->getDefaultConceptScheme();
473
        }
474
475
        /* encode the results in a JSON-LD compatible array */
476
        $topconcepts = $vocab->getTopConcepts($scheme, $request->getLang());
477
478
        $ret = array_merge_recursive($this->context, array(
479
            '@context' => array('onki' => 'http://schema.onki.fi/onki#', 'topconcepts' => 'skos:hasTopConcept', 'notation' => 'skos:notation', 'label' => 'skos:prefLabel', '@language' => $request->getLang()),
480
            'uri' => $scheme,
481
            'topconcepts' => $topconcepts)
482
        );
483
484
        return $this->returnJson($ret);
485
    }
486
487
    private function redirectToVocabData($request) {
488
        $urls = $request->getVocab()->getConfig()->getDataURLs();
489
        if (sizeof($urls) == 0) {
490
            $vocid = $request->getVocab()->getId();
491
            return $this->returnError('404', 'Not Found', "No download source URL known for vocabulary $vocid");
492
        }
493
494
        $format = $this->negotiateFormat(array_keys($urls), $request->getServerConstant('HTTP_ACCEPT'), $request->getQueryParam('format'));
495
        if (!$format) {
496
            return $this->returnError(406, 'Not Acceptable', "Unsupported format. Supported MIME types are: " . implode(' ', array_keys($urls)));
497
        }
498
499
        header("Location: " . $urls[$format]);
500
    }
501
    
502
    private function returnDataResults($results, $format) {
503
        if ($format == 'application/ld+json' || $format == 'application/json') {
504
            // further compact JSON-LD document using a context
505
            $context = array(
506
                'skos' => 'http://www.w3.org/2004/02/skos/core#',
507
                'isothes' => 'http://purl.org/iso25964/skos-thes#',
508
                'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
509
                'owl' => 'http://www.w3.org/2002/07/owl#',
510
                'dct' => 'http://purl.org/dc/terms/',
511
                'dc11' => 'http://purl.org/dc/elements/1.1/',
512
                'uri' => '@id',
513
                'type' => '@type',
514
                'lang' => '@language',
515
                'value' => '@value',
516
                'graph' => '@graph',
517
                'label' => 'rdfs:label',
518
                'prefLabel' => 'skos:prefLabel',
519
                'altLabel' => 'skos:altLabel',
520
                'hiddenLabel' => 'skos:hiddenLabel',
521
                'broader' => 'skos:broader',
522
                'narrower' => 'skos:narrower',
523
                'related' => 'skos:related',
524
                'inScheme' => 'skos:inScheme',
525
            );
526
            $compactJsonLD = \ML\JsonLD\JsonLD::compact($results, json_encode($context));
527
            $results = \ML\JsonLD\JsonLD::toString($compactJsonLD);
528
        }
529
530
        header("Content-type: $format; charset=utf-8");
531
        echo $results;
532
    }
533
534
    /**
535
     * Download a concept as json-ld or redirect to download the whole vocabulary.
536
     * @param Request $request
537
     * @return object json-ld formatted concept.
538
     */
539
    public function data($request)
540
    {
541
        $vocab = $request->getVocab();
542
543
        if ($request->getUri()) {
544
            $uri = $request->getUri();
545
        } else if ($vocab !== null) { // whole vocabulary - redirect to download URL
546
            return $this->redirectToVocabData($request);
547
        } else {
548
            return $this->returnError(400, 'Bad Request', "uri parameter missing");
549
        }
550
551
        $format = $this->negotiateFormat(explode(' ', self::SUPPORTED_FORMATS), $request->getServerConstant('HTTP_ACCEPT'), $request->getQueryParam('format'));
552
        if (!$format) {
553
            return $this->returnError(406, 'Not Acceptable', "Unsupported format. Supported MIME types are: " . self::SUPPORTED_FORMATS);
554
        }
555
556
        $vocid = $vocab ? $vocab->getId() : null;
557
        $results = $this->model->getRDF($vocid, $uri, $format);
558
        return $this->returnDataResults($results, $format);
559
    }
560
561
    /**
562
     * Used for querying labels for a uri.
563
     * @param Request $request
564
     * @return object json-ld wrapped labels.
565
     */
566
    public function label($request)
567
    {
568
        if (!$request->getUri()) {
569
            return $this->returnError(400, "Bad Request", "uri parameter missing");
570
        }
571
572
        $results = $request->getVocab()->getConceptLabel($request->getUri(), $request->getLang());
573
        if ($results === null) {
574
            return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>");
575
        }
576
577
        $ret = array_merge_recursive($this->context, array(
578
            '@context' => array('prefLabel' => 'skos:prefLabel', '@language' => $request->getLang()),
579
            'uri' => $request->getUri())
580
        );
581
582
        if (isset($results[$request->getLang()])) {
583
            $ret['prefLabel'] = $results[$request->getLang()]->getValue();
584
        }
585
586
        return $this->returnJson($ret);
587
    }
588
    
589
    private function transformPropertyResults($uri, $lang, $objects, $propname, $propuri)
590
    {
591
        $results = array();
592
        foreach ($objects as $objuri => $vals) {
593
            $results[] = array('uri' => $objuri, 'prefLabel' => $vals['label']);
594
        }
595
596
        $ret = array_merge_recursive($this->context, array(
597
            '@context' => array('prefLabel' => 'skos:prefLabel', $propname => $propuri, '@language' => $lang),
598
            'uri' => $uri,
599
            $propname => $results)
600
        );
601
        return $ret;    
602
    }
603
    
604
    private function transformTransitivePropertyResults($uri, $lang, $objects, $tpropname, $tpropuri, $dpropname, $dpropuri)
605
    {
606
        $results = array();
607
        foreach ($objects as $objuri => $vals) {
608
            $result = array('uri' => $objuri, 'prefLabel' => $vals['label']);
609
            if (isset($vals['direct'])) {
610
                $result[$dpropname] = $vals['direct'];
611
            }
612
            $results[$objuri] = $result;
613
        }
614
615
        $ret = array_merge_recursive($this->context, array(
616
            '@context' => array('prefLabel' => 'skos:prefLabel', $dpropname => array('@id' => $dpropuri, '@type' => '@id'), $tpropname => array('@id' => $tpropuri, '@container' => '@index'), '@language' => $lang),
617
            'uri' => $uri,
618
            $tpropname => $results)
619
        );
620
        return $ret;
621
    }
622
623
    /**
624
     * Used for querying broader relations for a concept.
625
     * @param Request $request
626
     * @return object json-ld wrapped broader concept uris and labels.
627
     */
628
    public function broader($request)
629
    {
630
        $broaders = $request->getVocab()->getConceptBroaders($request->getUri(), $request->getLang());
631
        if ($broaders === null) {
632
            return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>");
633
        }
634
        $ret = $this->transformPropertyResults($request->getUri(), $request->getLang(), $broaders, "broader", "skos:broader");
635
        return $this->returnJson($ret);
636
    }
637
638
    /**
639
     * Used for querying broader transitive relations for a concept.
640
     * @param Request $request
641
     * @return object json-ld wrapped broader transitive concept uris and labels.
642
     */
643 View Code Duplication
    public function broaderTransitive($request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
644
    {
645
        $broaders = $request->getVocab()->getConceptTransitiveBroaders($request->getUri(), $this->parseLimit(), false, $request->getLang());
646
        if (empty($broaders)) {
647
            return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>");
648
        }
649
        $ret = $this->transformTransitivePropertyResults($request->getUri(), $request->getLang(), $broaders, "broaderTransitive", "skos:broaderTransitive", "broader", "skos:broader");
650
        return $this->returnJson($ret);
651
    }
652
653
    /**
654
     * Used for querying narrower relations for a concept.
655
     * @param Request $request
656
     * @return object json-ld wrapped narrower concept uris and labels.
657
     */
658 View Code Duplication
    public function narrower($request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
659
    {
660
        $narrowers = $request->getVocab()->getConceptNarrowers($request->getUri(), $request->getLang());
661
        if ($narrowers === null) {
662
            return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>");
663
        }
664
        $ret = $this->transformPropertyResults($request->getUri(), $request->getLang(), $narrowers, "narrower", "skos:narrower");
665
        return $this->returnJson($ret);
666
    }
667
668
    /**
669
     * Used for querying narrower transitive relations for a concept.
670
     * @param Request $request
671
     * @return object json-ld wrapped narrower transitive concept uris and labels.
672
     */
673 View Code Duplication
    public function narrowerTransitive($request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
674
    {
675
        $narrowers = $request->getVocab()->getConceptTransitiveNarrowers($request->getUri(), $this->parseLimit(), $request->getLang());
676
        if (empty($narrowers)) {
677
            return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>");
678
        }
679
        $ret = $this->transformTransitivePropertyResults($request->getUri(), $request->getLang(), $narrowers, "narrowerTransitive", "skos:narrowerTransitive", "narrower", "skos:narrower");
680
        return $this->returnJson($ret);
681
    }
682
683
    /**
684
     * Used for querying broader transitive relations
685
     * and some narrowers for a concept in the hierarchy view.
686
     * @param Request $request
687
     * @return object json-ld wrapped hierarchical concept uris and labels.
688
     */
689
    public function hierarchy($request)
690
    {
691
        $results = $request->getVocab()->getConceptHierarchy($request->getUri(), $request->getLang());
692
        if (empty($results)) {
693
            return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>");
694
        }
695
696
        if ($request->getVocab()->getConfig()->getShowHierarchy()) {
697
            $schemes = $request->getVocab()->getConceptSchemes($request->getLang());
698
            foreach ($schemes as $scheme) {
699
                if (!isset($scheme['title']) && !isset($scheme['label']) && !isset($scheme['prefLabel'])) {
700
                    unset($schemes[array_search($scheme, $schemes)]);
701
                }
702
703
            }
704
705
            /* encode the results in a JSON-LD compatible array */
706
            $topconcepts = $request->getVocab()->getTopConcepts(array_keys($schemes), $request->getLang());
707
            foreach ($topconcepts as $top) {
708
                if (!isset($results[$top['uri']])) {
709
                    $results[$top['uri']] = array('uri' => $top['uri'], 'top' => $top['topConceptOf'], 'prefLabel' => $top['label'], 'hasChildren' => $top['hasChildren']);
710
                    if (isset($top['notation'])) {
711
                        $results[$top['uri']]['notation'] = $top['notation'];
712
                    }
713
714
                }
715
            }
716
        }
717
718
        $ret = array_merge_recursive($this->context, array(
719
            '@context' => array('onki' => 'http://schema.onki.fi/onki#', 'prefLabel' => 'skos:prefLabel', 'notation' => 'skos:notation', 'narrower' => array('@id' => 'skos:narrower', '@type' => '@id'), 'broader' => array('@id' => 'skos:broader', '@type' => '@id'), 'broaderTransitive' => array('@id' => 'skos:broaderTransitive', '@container' => '@index'), 'top' => array('@id' => 'skos:topConceptOf', '@type' => '@id'), 'hasChildren' => 'onki:hasChildren', '@language' => $request->getLang()),
720
            'uri' => $request->getUri(),
721
            'broaderTransitive' => $results)
722
        );
723
724
        return $this->returnJson($ret);
725
    }
726
727
    /**
728
     * Used for querying group hierarchy for the sidebar group view.
729
     * @param Request $request
730
     * @return object json-ld wrapped hierarchical concept uris and labels.
731
     */
732
    public function groups($request)
733
    {
734
        $results = $request->getVocab()->listConceptGroups($request->getLang());
735
736
        $ret = array_merge_recursive($this->context, array(
737
            '@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()),
738
            'uri' => '',
739
            'groups' => $results)
740
        );
741
742
        return $this->returnJson($ret);
743
    }
744
745
    /**
746
     * Used for querying member relations for a group.
747
     * @param Request $request
748
     * @return object json-ld wrapped narrower concept uris and labels.
749
     */
750
    public function groupMembers($request)
751
    {
752
        $children = $request->getVocab()->listConceptGroupContents($request->getUri(), $request->getLang());
753
        if (empty($children)) {
754
            return $this->returnError('404', 'Not Found', "Could not find group <{$request->getUri()}>");
755
        }
756
757
        $ret = array_merge_recursive($this->context, array(
758
            '@context' => array('prefLabel' => 'skos:prefLabel', 'members' => 'skos:member', '@language' => $request->getLang()),
759
            'uri' => $request->getUri(),
760
            'members' => $children)
761
        );
762
763
        return $this->returnJson($ret);
764
    }
765
766
    /**
767
     * Used for querying narrower relations for a concept in the hierarchy view.
768
     * @param Request $request
769
     * @return object json-ld wrapped narrower concept uris and labels.
770
     */
771
    public function children($request)
772
    {
773
        $children = $request->getVocab()->getConceptChildren($request->getUri(), $request->getLang());
774
        if ($children === null) {
775
            return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>");
776
        }
777
778
        $ret = array_merge_recursive($this->context, array(
779
            '@context' => array('prefLabel' => 'skos:prefLabel', 'narrower' => 'skos:narrower', 'notation' => 'skos:notation', 'hasChildren' => 'onki:hasChildren', '@language' => $request->getLang()),
780
            'uri' => $request->getUri(),
781
            'narrower' => $children)
782
        );
783
784
        return $this->returnJson($ret);
785
    }
786
787
    /**
788
     * Used for querying narrower relations for a concept in the hierarchy view.
789
     * @param Request $request
790
     * @return object json-ld wrapped hierarchical concept uris and labels.
791
     */
792 View Code Duplication
    public function related($request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
793
    {
794
        $related = $request->getVocab()->getConceptRelateds($request->getUri(), $request->getLang());
795
        if ($related === null) {
796
            return $this->returnError('404', 'Not Found', "Could not find concept <{$request->getUri()}>");
797
        }
798
        $ret = $this->transformPropertyResults($request->getUri(), $request->getLang(), $related, "related", "skos:related");
799
        return $this->returnJson($ret);
800
    }
801
}
802