Completed
Push — master ( 630a63...988c90 )
by Henri
02:39
created

Model::getConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 17 and the first side effect is on line 6.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
/**
4
 * Setting some often needed namespace prefixes
5
 */
6
EasyRdf_Namespace::set('skosmos', 'http://purl.org/net/skosmos#');
7
EasyRdf_Namespace::set('void', 'http://rdfs.org/ns/void#');
8
EasyRdf_Namespace::set('skosext', 'http://purl.org/finnonto/schema/skosext#');
9
EasyRdf_Namespace::set('isothes', 'http://purl.org/iso25964/skos-thes#');
10
EasyRdf_Namespace::set('mads', 'http://www.loc.gov/mads/rdf/v1#');
11
12
/**
13
 * Model provides access to the data.
14
 * @property EasyRdf_Graph $graph
15
 * @property GlobalConfig $globalConfig
16
 */
17
class Model
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...
18
{
19
    /** EasyRdf_Graph graph instance */
20
    private $graph;
21
    /** Namespaces from vocabularies configuration file */
22
    private $namespaces;
23
    /** cache for Vocabulary objects */
24
    private $allVocabularies = null;
25
    /** cache for Vocabulary objects */
26
    private $vocabsByGraph = null;
27
    /** cache for Vocabulary objects */
28
    private $vocabsByUriSpace = null;
29
    /** how long to store retrieved URI information in APC cache */
30
    const URI_FETCH_TTL = 86400; // 1 day
31
    private $globalConfig;
32
    private $cache;
33
34
    /**
35
     * Initializes the Model object
36
     */
37
    public function __construct($config)
38
    {
39
        $this->globalConfig = $config;
40
        try {
41
          $this->cache = new Cache();
42
          $this->initializeVocabularies();
43
          $this->initializeNamespaces();
44
          $this->initializeLogging();
45
        } catch (Exception $e) {
46
            header("HTTP/1.0 404 Not Found");
47
            echo("Error: Vocabularies configuration file 'vocabularies.ttl' not found.");
48
            return;
49
        }
50
    }
51
52
    /**
53
     * Returns the GlobalConfig object given to the Model as a constructor parameter.
54
     * @return GlobalConfig
55
     */
56
    public function getConfig() {
57
      return $this->globalConfig;
58
    }
59
60
    /**
61
     * Initializes the configuration from the vocabularies.ttl file
62
     */
63
    private function initializeVocabularies()
64
    {
65
        if (!file_exists($this->getConfig()->getVocabularyConfigFile())) {
66
            throw new Exception($this->getConfig()->getVocabularyConfigFile() . ' is missing, please provide one.');
67
        }
68
69
        try {
70
            // use APC user cache to store parsed vocabularies.ttl configuration
71
            if ($this->cache->isAvailable()) {
72
                // @codeCoverageIgnoreStart
73
                $key = realpath($this->getConfig()->getVocabularyConfigFile()) . ", " . filemtime($this->getConfig()->getVocabularyConfigFile());
74
                $nskey = "namespaces of " . $key;
75
                $this->graph = $this->cache->fetch($key);
76
                $this->namespaces = $this->cache->fetch($nskey);
77
                if ($this->graph === false || $this->namespaces === false) { // was not found in cache
78
                    $this->parseVocabularies($this->getConfig()->getVocabularyConfigFile());
79
                    $this->cache->store($key, $this->graph);
80
                    $this->cache->store($nskey, $this->namespaces);
81
                }
82
                // @codeCoverageIgnoreEnd
83
            } else { // APC not available, parse on every request
84
                $this->parseVocabularies($this->getConfig()->getVocabularyConfigFile());
85
            }
86
        } catch (Exception $e) {
87
            echo "Error: " . $e->getMessage();
88
        }
89
    }
90
91
    /**
92
     * Parses vocabulary configuration and RDF namespaces from the vocabularies.ttl file
93
     * @param string $filename path to vocabularies.ttl file
94
     */
95
96
    private function parseVocabularies($filename)
97
    {
98
        $this->graph = new EasyRdf_Graph();
99
        $parser = new NamespaceExposingTurtleParser();
100
        $parser->parse($this->graph, file_get_contents($filename), 'turtle', $filename);
101
        $this->namespaces = $parser->getNamespaces();
102
    }
103
104
    /**
105
     * Registers RDF namespaces from the vocabularies.ttl file for use by EasyRdf (e.g. serializing)
106
     */
107
    
108
    private function initializeNamespaces() {
109
        foreach ($this->namespaces as $prefix => $fullUri) {
110
            if ($prefix != '' && EasyRdf_Namespace::get($prefix) === null) // if not already defined
111
            {
112
                EasyRdf_Namespace::set($prefix, $fullUri);
113
            }
114
        }
115
    }
116
    
117
    /**
118
     * Configures the logging facility
119
     */
120
    private function initializeLogging() {
121
        $this->logger = new \Monolog\Logger('general');
0 ignored issues
show
Bug introduced by
The property logger does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
122
        $formatter = new \Monolog\Formatter\LineFormatter("[%datetime%] %level_name% %message%\n");
123
        $formatter->allowInlineLineBreaks(true);
124
        if ($this->getConfig()->getLoggingBrowserConsole()) {
125
            $browserHandler = new \Monolog\Handler\BrowserConsoleHandler(\Monolog\Logger::INFO);
126
            $browserHandler->setFormatter($formatter);
127
            $this->logger->pushHandler($browserHandler);
128
        }
129
        if ($this->getConfig()->getLoggingFilename() !== null) {
130
            $streamHandler = new \Monolog\Handler\StreamHandler($this->getConfig()->getLoggingFilename(), \Monolog\Logger::INFO);
131
            $streamHandler->setFormatter($formatter);
132
            $this->logger->pushHandler($streamHandler);
133
        }
134
        if (!$this->logger->getHandlers()) {
135
            // add a NullHandler to suppress the default Monolog logging to stderr
136
            $nullHandler = new \Monolog\Handler\NullHandler();
137
            $this->logger->pushHandler($nullHandler);
138
        }
139
    }
140
    
141
    /**
142
     * Return the logging facility
143
     * @return object logger
144
     */
145
    public function getLogger() {
146
        return $this->logger;
147
    }
148
149
    /**
150
     * Return the version of this Skosmos installation, or "unknown" if
151
     * it cannot be determined. The version information is based on Git tags.
152
     * @return string version
153
     */
154
    public function getVersion()
155
    {
156
        $ver = null;
157
        if (file_exists('.git')) {
158
            $ver = shell_exec('git describe --tags');
159
        }
160
161
        if ($ver === null) {
162
            return "unknown";
163
        }
164
165
        return $ver;
166
    }
167
168
    /**
169
     * Return all the vocabularies available.
170
     * @param boolean $categories whether you want everything included in a subarray of
171
     * a category.
172
     * @param boolean $shortname set to true if you want the vocabularies sorted by 
173
     * their shortnames instead of ther titles.
174
     */
175
    public function getVocabularyList($categories = true, $shortname = false)
176
    {
177
        $cats = $this->getVocabularyCategories();
178
        $ret = array();
179
        foreach ($cats as $cat) {
180
            $catlabel = $cat->getTitle();
181
182
            // find all the vocabs in this category
183
            $vocs = array();
184
            foreach ($cat->getVocabularies() as $voc) {
185
                $vocs[$shortname ? $voc->getConfig()->getShortname() : $voc->getConfig()->getTitle()] = $voc;
186
            }
187
            uksort($vocs, 'strcoll');
188
189
            if (sizeof($vocs) > 0 && $categories) {
190
                $ret[$catlabel] = $vocs;
191
            } elseif (sizeof($vocs) > 0) {
192
                $ret = array_merge($ret, $vocs);
193
            }
194
195
        }
196
197
        if (!$categories) {
198
            uksort($ret, 'strcoll');
199
        }
200
201
        return $ret;
202
    }
203
204
    /**
205
     * Return all types (RDFS/OWL classes) present in the specified vocabulary or all vocabularies.
206
     * @return array Array with URIs (string) as key and array of (label, superclassURI) as value
207
     */
208
    public function getTypes($vocid = null, $lang = null)
209
    {
210
        $sparql = (isset($vocid)) ? $this->getVocabulary($vocid)->getSparql() : $this->getDefaultSparql();
211
        $result = $sparql->queryTypes($lang);
212
213
        foreach ($result as $uri => $values) {
214
            if (empty($values)) {
215
                $shorteneduri = EasyRdf_Namespace::shorten($uri);
216
                if ($shorteneduri !== null) {
217
                    $trans = gettext($shorteneduri);
218
                    if ($trans) {
219
                        $result[$uri] = array('label' => $trans);
220
                    }
221
                }
222
            }
223
        }
224
225
        return $result;
226
    }
227
228
    /**
229
     * Return the languages present in the configured vocabularies.
230
     * @return array Array with lang codes (string)
231
     */
232
    public function getLanguages($lang)
233
    {
234
        $vocabs = $this->getVocabularyList(false);
235
        $ret = array();
236
        foreach ($vocabs as $vocab) {
237
            foreach ($vocab->getConfig()->getLanguages() as $langcode) {
238
                $langlit = Punic\Language::getName($langcode, $lang);
239
                $ret[$langlit] = $langcode;
240
            }
241
        }
242
        ksort($ret);
243
        return array_unique($ret);
244
    }
245
246
    /**
247
     * returns a concept's RDF data in downloadable format
248
     * @param string $vocid vocabulary id, or null for global data (from all vocabularies)
249
     * @param string $uri concept URI
250
     * @param string $format the format in which you want to get the result, currently this function supports
251
     * text/turtle, application/rdf+xml and application/json
252
     * @return string RDF data in the requested serialization
253
     */
254
    public function getRDF($vocid, $uri, $format)
255
    {
256
257
        if ($format == 'text/turtle') {
258
            $retform = 'turtle';
259
            $serialiser = new EasyRdf_Serialiser_Turtle();
260
        } elseif ($format == 'application/ld+json' || $format == 'application/json') {
261
            $retform = 'jsonld'; // serve JSON-LD for both JSON-LD and plain JSON requests
262
            $serialiser = new EasyRdf_Serialiser_JsonLd();
263
        } else {
264
            $retform = 'rdfxml';
265
            $serialiser = new EasyRdf_Serialiser_RdfXml();
266
        }
267
268
        if ($vocid !== null) {
269
            $vocab = $this->getVocabulary($vocid);
270
            $sparql = $vocab->getSparql();
271
            $arrayClass = $vocab->getConfig()->getArrayClassURI();
272
            $vocabs = array($vocab);
273
        } else {
274
            $sparql = $this->getDefaultSparql();
275
            $arrayClass = null;
276
            $vocabs = null;
277
        }
278
        $result = $sparql->queryConceptInfoGraph($uri, $arrayClass, $vocabs);
279
280
        if (!$result->isEmpty()) {
281
            return $serialiser->serialise($result, $retform);
282
        }
283
    }
284
285
    /**
286
     * Makes a SPARQL-query to the endpoint that retrieves concept
287
     * references as it's search results.
288
     * @param ConceptSearchParameters $params an object that contains all the parameters needed for the search
289
     * @return array search results
290
     */
291
    public function searchConcepts($params)
292
    {
293
        // don't even try to search for empty prefix if no other search criteria (group or parent concept) has been set
294
        if (($params->getSearchTerm() === "" || !preg_match('/[^*]/', $params->getSearchTerm())) && !$params->getGroupLimit() && !$params->getParentLimit()) {
295
            return array();
296
        }
297
298
        $vocabs = $params->getVocabs();
299
300
        if (sizeof($vocabs) === 1) { // search within vocabulary
301
            $voc = $vocabs[0];
302
            $sparql = $voc->getSparql();
303
        } else { // multi-vocabulary or global search
304
            $voc = null;
305
            $sparql = $this->getDefaultSparql();
306
        }
307
308
        $results = $sparql->queryConcepts($vocabs, $params->getAdditionalFields(), $params->getUnique(), $params);
309
        if ($params->getRest() && $results && $params->getSearchLimit() !== 0) {
310
          $results = array_slice($results, $params->getOffset(), $params->getSearchLimit());
311
        }
312
        $ret = array();
313
314
        foreach ($results as $hit) {
315
            if (sizeof($vocabs) == 1) {
316
                $hit['vocab'] = $vocabs[0]->getId();
317
            } else {
318
                try {
319
                    $voc = $this->getVocabularyByGraph($hit['graph']);
320
                    $hit['vocab'] = $voc->getId();
321
                } catch (Exception $e) {
322
                    trigger_error($e->getMessage(), E_USER_WARNING);
323
                    $voc = null;
324
                    $hit['vocab'] = "???";
325
                }
326
            }
327
            unset($hit['graph']);
328
329
            $hit['voc'] = $voc;
330
331
            // if uri is a external vocab uri that is included in the current vocab
332
            $realvoc = $this->guessVocabularyFromURI($hit['uri']);
333
            if ($realvoc != $voc) {
334
                unset($hit['localname']);
335
                $hit['exvocab'] = ($realvoc !== null) ? $realvoc->getId() : "???";
336
            }
337
338
            $ret[] = $hit;
339
        }
340
341
        return $ret;
342
    }
343
344
    /**
345
     * Function for performing a search for concepts and their data fields.
346
     * @param ConceptSearchParameters $params an object that contains all the parameters needed for the search
347
     * @return array array with keys 'count' and 'results'
348
     */
349
    public function searchConceptsAndInfo($params)
350
    {
351
        $params->setUnique(true);
352
        $allhits = $this->searchConcepts($params);
353
        $count = sizeof($allhits);
354
        $hits = array_slice($allhits, $params->getOffset(), $params->getSearchLimit());
355
356
        $uris = array();
357
        $vocabs = array();
358
        $uniqueVocabs = array();
359
        foreach ($hits as $hit) {
360
            $uniqueVocabs[$hit['voc']->getId()] = $hit['voc']->getId();
361
            $vocabs[] = $hit['voc'];
362
            $uris[] = $hit['uri'];
363
        }
364
        if (sizeof($uniqueVocabs) == 1) {
365
            $voc = $vocabs[0];
366
            $sparql = $voc->getSparql();
367
            $arrayClass = $voc->getConfig()->getArrayClassURI();
368
        } else {
369
            $arrayClass = null;
370
            $sparql = $this->getDefaultSparql();
371
        }
372
        $ret = $sparql->queryConceptInfo($uris, $arrayClass, $vocabs, $params->getSearchLang());
373
374
        // For marking that the concept has been found through an alternative label, hidden
375
        // label or a label in another language
376
        foreach ($hits as $idx => $hit) {
377
            if (isset($hit['altLabel']) && isset($ret[$idx])) {
378
                $ret[$idx]->setFoundBy($hit['altLabel'], 'alt');
379
            }
380
381
            if (isset($hit['hiddenLabel']) && isset($ret[$idx])) {
382
                $ret[$idx]->setFoundBy($hit['hiddenLabel'], 'hidden');
383
            }
384
385
            if (isset($hit['matchedPrefLabel'])) {
386
                $ret[$idx]->setFoundBy($hit['matchedPrefLabel'], 'lang');
387
            }
388
389
            if ($ret[$idx] && isset($hit['lang'])) {
390
                $ret[$idx]->setContentLang($hit['lang']);
391
            }
392
393
        }
394
395
        return array('count' => $count, 'results' => $ret);
396
    }
397
398
    /**
399
     * Creates dataobjects from an input array.
400
     * @param string $class the type of class eg. 'Vocabulary'.
401
     * @param array $resarr contains the EasyRdf_Resources.
402
     */
403
    private function createDataObjects($class, $resarr)
404
    {
405
        $ret = array();
406
        foreach ($resarr as $res) {
407
            $ret[] = new $class($this, $res);
408
        }
409
410
        return $ret;
411
    }
412
413
    /**
414
     * Returns the cached vocabularies.
415
     * @return array of Vocabulary dataobjects
416
     */
417
    public function getVocabularies()
418
    {
419
        if ($this->allVocabularies === null) { // initialize cache
420
            $vocs = $this->graph->allOfType('skosmos:Vocabulary');
421
            $this->allVocabularies = $this->createDataObjects("Vocabulary", $vocs);
422
            foreach ($this->allVocabularies as $voc) {
423
                // register vocabulary ids as RDF namespace prefixes
424
                $prefix = preg_replace('/\W+/', '', $voc->getId()); // strip non-word characters
425
                try {
426
                    if ($prefix != '' && EasyRdf_Namespace::get($prefix) === null) // if not already defined
427
                    {
428
                        EasyRdf_Namespace::set($prefix, $voc->getUriSpace());
429
                    }
430
431
                } catch (Exception $e) {
432
                    // not valid as namespace identifier, ignore
433
                }
434
            }
435
        }
436
437
        return $this->allVocabularies;
438
    }
439
440
    /**
441
     * Returns the cached vocabularies from a category.
442
     * @param EasyRdf_Resource $cat the category in question
443
     * @return array of vocabulary dataobjects
444
     */
445
    public function getVocabulariesInCategory($cat)
446
    {
447
        $vocs = $this->graph->resourcesMatching('dc:subject', $cat);
448
449
        return $this->createDataObjects("Vocabulary", $vocs);
450
    }
451
452
    /**
453
     * Creates dataobjects of all the different vocabulary categories (Health etc.).
454
     * @return array of Dataobjects of the type VocabularyCategory.
455
     */
456
    public function getVocabularyCategories()
457
    {
458
        $cats = $this->graph->allOfType('skos:Concept');
459
        if(empty($cats)) {
460
            return array(new VocabularyCategory($this, null));
461
        }
462
463
        return $this->createDataObjects("VocabularyCategory", $cats);
464
    }
465
466
    /**
467
     * Returns the label defined in vocabularies.ttl with the appropriate language.
468
     * @param string $lang language code of returned labels, eg. 'fi'
469
     * @return string the label for vocabulary categories.
470
     */
471
    public function getClassificationLabel($lang)
472
    {
473
        $cats = $this->graph->allOfType('skos:ConceptScheme');
474
        $label = $cats ? $cats[0]->label($lang) : null;
475
476
        return $label;
477
    }
478
479
    /**
480
     * Returns a single cached vocabulary.
481
     * @param string $vocid the vocabulary id eg. 'mesh'.
482
     * @return vocabulary dataobject
483
     */
484
    public function getVocabulary($vocid)
485
    {
486
        $vocs = $this->getVocabularies();
487
        foreach ($vocs as $voc) {
488
            if ($voc->getId() == $vocid) {
489
                return $voc;
490
            }
491
        }
492
        throw new Exception("Vocabulary id '$vocid' not found in configuration.");
493
    }
494
495
    /**
496
     * Return the vocabulary that is stored in the given graph on the given endpoint.
497
     *
498
     * @param $graph string graph URI
499
     * @param $endpoint string endpoint URL (default SPARQL endpoint if omitted)
500
     * @return Vocabulary vocabulary of this URI, or null if not found
501
     */
502
    public function getVocabularyByGraph($graph, $endpoint = null)
503
    {
504
        if ($endpoint === null) {
505
            $endpoint = $this->getConfig()->getDefaultEndpoint();
506
        }
507
        if ($this->vocabsByGraph === null) { // initialize cache
508
            $this->vocabsByGraph = array();
509
            foreach ($this->getVocabularies() as $voc) {
510
                $key = json_encode(array($voc->getGraph(), $voc->getEndpoint()));
511
                $this->vocabsByGraph[$key] = $voc;
512
            }
513
        }
514
515
        $key = json_encode(array($graph, $endpoint));
516
        if (array_key_exists($key, $this->vocabsByGraph)) {
517
            return $this->vocabsByGraph[$key];
518
        } else {
519
            throw new Exception("no vocabulary found for graph $graph and endpoint $endpoint");
520
        }
521
522
    }
523
    
524
    /**
525
     * When multiple vocabularies share same URI namespace, return the
526
     * vocabulary in which the URI is actually defined (has a label).
527
     *
528
     * @param Vocabulary[] $vocabs vocabularies to search
529
     * @param string $uri URI to look for
530
     * @return Vocabulary the vocabulary with the URI
531
     */
532
533
    private function disambiguateVocabulary($vocabs, $uri)
534
    {
535
        // if there is only one candidate vocabulary, return it
536
        if (sizeof($vocabs) == 1) {
537
            return $vocabs[0];
538
        }
539
        
540
        foreach ($vocabs as $vocab) {
541
            if ($vocab->getConceptLabel($uri, null) !== null)
542
                return $vocab;
543
        }
544
545
        // if the URI couldn't be found, fall back to the first vocabulary
546
        return $vocabs[0];
547
    }
548
549
    /**
550
     * Guess which vocabulary a URI originates from, based on the declared
551
     * vocabulary URI spaces.
552
     *
553
     * @param $uri string URI to search
554
     * @return Vocabulary vocabulary of this URI, or null if not found
555
     */
556
    public function guessVocabularyFromURI($uri)
557
    {
558
        if ($this->vocabsByUriSpace === null) { // initialize cache
559
            $this->vocabsByUriSpace = array();
560
            foreach ($this->getVocabularies() as $voc) {
561
                $this->vocabsByUriSpace[$voc->getUriSpace()][] = $voc;
562
            }
563
        }
564
565
        // try to guess the URI space and look it up in the cache
566
        $res = new EasyRdf_Resource($uri);
567
        $namespace = substr($uri, 0, -strlen($res->localName()));
568
        if (array_key_exists($namespace, $this->vocabsByUriSpace)) {
569
            $vocabs = $this->vocabsByUriSpace[$namespace];
570
            return $this->disambiguateVocabulary($vocabs, $uri);
571
        }
572
573
        // didn't work, try to match with each URI space separately
574
        foreach ($this->vocabsByUriSpace as $urispace => $vocabs) {
575
            if (strpos($uri, $urispace) === 0) {
576
                return $this->disambiguateVocabulary($vocabs, $uri);
577
            }
578
        }
579
580
        // not found
581
        return null;
582
    }
583
584
    /**
585
     * Get the label for a resource, preferring 1. the given language 2. configured languages 3. any language.
586
     * @param EasyRdf_Resource $res resource whose label to return
587
     * @param string $lang preferred language
588
     * @return EasyRdf_Literal label as an EasyRdf_Literal object, or null if not found
589
     */
590
    public function getResourceLabel($res, $lang)
591
    {
592
        $langs = array_merge(array($lang), array_keys($this->getConfig()->getLanguages()));
593
        foreach ($langs as $l) {
594
            $label = $res->label($l);
595
            if ($label !== null) {
596
                return $label;
597
            }
598
599
        }
600
        return $res->label(); // desperate check for label in any language; will return null if even this fails
601
    }
602
603
    private function fetchResourceFromUri($uri)
604
    {
605
        try {
606
            // change the timeout setting for external requests
607
            $httpclient = EasyRdf_Http::getDefaultHttpClient();
608
            $httpclient->setConfig(array('timeout' => $this->getConfig()->getHttpTimeout()));
609
            EasyRdf_Http::setDefaultHttpClient($httpclient);
610
611
            $client = EasyRdf_Graph::newAndLoad(EasyRdf_Utils::removeFragmentFromUri($uri));
612
            return $client->resource($uri);
613
        } catch (Exception $e) {
614
            return null;
615
        }
616
    }
617
618
    public function getResourceFromUri($uri)
619
    {
620
        // prevent parsing errors for sources which return invalid JSON (see #447)
621
        // 1. Unregister the legacy RDF/JSON parser, we don't want to use it
622
        EasyRdf_Format::unregister('json'); 
623
        // 2. Add "application/json" as a possible MIME type for the JSON-LD format
624
        $jsonld = EasyRdf_Format::getFormat('jsonld');
625
        $mimetypes = $jsonld->getMimeTypes();
626
        $mimetypes['application/json'] = 0.5;
627
        $jsonld->setMimeTypes($mimetypes);
628
        
629
        // using apc cache for the resource if available
630
        if ($this->cache->isAvailable()) {
631
            // @codeCoverageIgnoreStart
632
            $key = 'fetch: ' . EasyRdf_Utils::removeFragmentFromUri($uri);
633
            $resource = $this->cache->fetch($key);
634
            if ($resource === null || $resource === false) { // was not found in cache, or previous request failed
635
                $resource = $this->fetchResourceFromUri($uri);
636
                $this->cache->store($key, $resource, self::URI_FETCH_TTL);
637
            }
638
            // @codeCoverageIgnoreEnd
639
        } else { // APC not available, parse on every request
640
            $resource = $this->fetchResourceFromUri($uri);
641
        }
642
        return $resource;
643
    }
644
645
    /**
646
     * Returns a SPARQL endpoint object.
647
     * @param string $dialect eg. 'JenaText'.
648
     * @param string $endpoint url address of endpoint
649
     * @param string $graph uri for the target graph.
650
     */
651
    public function getSparqlImplementation($dialect, $endpoint, $graph)
652
    {
653
        $classname = $dialect . "Sparql";
654
655
        return new $classname($endpoint, $graph, $this);
656
    }
657
658
    /**
659
     * Returns a SPARQL endpoint object using the default implementation set in the config.inc.
660
     */
661
    public function getDefaultSparql()
662
    {
663
        return $this->getSparqlImplementation($this->getConfig()->getDefaultSparqlDialect(), $this->getConfig()->getDefaultEndpoint(), '?graph');
664
    }
665
666
}
667