Completed
Push — master ( e2f407...4b4359 )
by Osma
19s queued 13s
created

Model::disambiguateVocabulary()   C

Complexity

Conditions 12
Paths 33

Size

Total Lines 45
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 23
nc 33
nop 3
dl 0
loc 45
rs 6.9666
c 0
b 0
f 0

How to fix   Complexity   

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
/**
4
 * Model provides access to the data.
5
 * @property EasyRdf\Graph $graph
6
 * @property GlobalConfig $globalConfig
7
 */
8
class Model
9
{
10
    /** cache for Vocabulary objects */
11
    private $allVocabularies = null;
12
    /** cache for Vocabulary objects */
13
    private $vocabsByGraph = null;
14
    /** cache for Vocabulary objects */
15
    private $vocabsByUriSpace = null;
16
    /** how long to store retrieved URI information in APC cache */
17
    const URI_FETCH_TTL = 86400; // 1 day
18
    private $globalConfig;
19
    private $logger;
20
    private $resolver;
21
22
    /**
23
     * Initializes the Model object
24
     */
25
    public function __construct($config)
26
    {
27
        $this->globalConfig = $config;
28
        $this->initializeLogging();
29
        $this->resolver = new Resolver($this);
30
    }
31
32
    /**
33
     * Returns the GlobalConfig object given to the Model as a constructor parameter.
34
     * @return GlobalConfig
35
     */
36
    public function getConfig() {
37
      return $this->globalConfig;
38
    }
39
40
    /**
41
     * Configures the logging facility
42
     */
43
    private function initializeLogging() {
44
        $this->logger = new \Monolog\Logger('general');
45
        $formatter = new \Monolog\Formatter\LineFormatter("[%datetime%] %level_name% %message%\n");
46
        $formatter->allowInlineLineBreaks(true);
47
        if ($this->getConfig()->getLoggingBrowserConsole()) {
48
            $browserHandler = new \Monolog\Handler\BrowserConsoleHandler(\Monolog\Logger::INFO);
49
            $browserHandler->setFormatter($formatter);
50
            $this->logger->pushHandler($browserHandler);
51
        }
52
        if ($this->getConfig()->getLoggingFilename() !== null) {
0 ignored issues
show
introduced by
The condition $this->getConfig()->getLoggingFilename() !== null is always true.
Loading history...
53
            $streamHandler = new \Monolog\Handler\StreamHandler($this->getConfig()->getLoggingFilename(), \Monolog\Logger::INFO);
54
            $streamHandler->setFormatter($formatter);
55
            $this->logger->pushHandler($streamHandler);
56
        }
57
        if (!$this->logger->getHandlers()) {
58
            // add a NullHandler to suppress the default Monolog logging to stderr
59
            $nullHandler = new \Monolog\Handler\NullHandler();
60
            $this->logger->pushHandler($nullHandler);
61
        }
62
    }
63
64
    /**
65
     * Return the logging facility
66
     * @return object logger
67
     */
68
    public function getLogger() {
69
        return $this->logger;
70
    }
71
72
    /**
73
     * Return the version of this Skosmos installation, or "unknown" if
74
     * it cannot be determined. The version information is based on Git tags.
75
     * @return string version
76
     */
77
    public function getVersion() : string
78
    {
79
        $ver = null;
80
        if (file_exists('.git')) {
81
            $ver = rtrim(shell_exec('git describe --tags --always'));
82
        }
83
84
        if ($ver === null) {
85
            return "unknown";
86
        }
87
88
        return $ver;
89
    }
90
91
    /**
92
     * Return all the vocabularies available.
93
     * @param boolean $categories whether you want everything included in a subarray of
94
     * a category.
95
     * @param boolean $shortname set to true if you want the vocabularies sorted by
96
     * their shortnames instead of their titles.
97
     */
98
    public function getVocabularyList($categories = true, $shortname = false)
99
    {
100
        $cats = $this->getVocabularyCategories();
101
        $ret = array();
102
        foreach ($cats as $cat) {
103
            $catlabel = $cat->getTitle();
104
105
            // find all the vocabs in this category
106
            $vocs = array();
107
            foreach ($cat->getVocabularies() as $voc) {
108
                $vocs[$shortname ? $voc->getConfig()->getShortname() : $voc->getConfig()->getTitle()] = $voc;
109
            }
110
            uksort($vocs, 'strcoll');
111
112
            if (sizeof($vocs) > 0 && $categories) {
113
                $ret[$catlabel] = $vocs;
114
            } elseif (sizeof($vocs) > 0) {
115
                $ret = array_merge($ret, $vocs);
116
            }
117
118
        }
119
120
        if (!$categories) {
121
            uksort($ret, 'strcoll');
122
        }
123
124
        return $ret;
125
    }
126
127
    /**
128
     * Return all types (RDFS/OWL classes) present in the specified vocabulary or all vocabularies.
129
     * @return array Array with URIs (string) as key and array of (label, superclassURI) as value
130
     */
131
    public function getTypes($vocid = null, $lang = null)
132
    {
133
        $sparql = (isset($vocid)) ? $this->getVocabulary($vocid)->getSparql() : $this->getDefaultSparql();
134
        $result = $sparql->queryTypes($lang);
135
136
        foreach ($result as $uri => $values) {
137
            if (empty($values)) {
138
                $shorteneduri = EasyRdf\RdfNamespace::shorten($uri);
139
                if ($shorteneduri !== null) {
140
                    $trans = gettext($shorteneduri);
141
                    if ($trans) {
142
                        $result[$uri] = array('label' => $trans);
143
                    }
144
                }
145
            }
146
        }
147
148
        return $result;
149
    }
150
151
    /**
152
     * Return the languages present in the configured vocabularies.
153
     * @return array Array with lang codes (string)
154
     */
155
    public function getLanguages($lang)
156
    {
157
        $vocabs = $this->getVocabularyList(false);
158
        $ret = array();
159
        foreach ($vocabs as $vocab) {
160
            foreach ($vocab->getConfig()->getLanguages() as $langcode) {
161
                $langlit = Punic\Language::getName($langcode, $lang);
162
                $ret[$langlit] = $langcode;
163
            }
164
        }
165
        ksort($ret);
166
        return array_unique($ret);
167
    }
168
169
    /**
170
     * returns a concept's RDF data in downloadable format
171
     * @param string $vocid vocabulary id, or null for global data (from all vocabularies)
172
     * @param string $uri concept URI
173
     * @param string $format the format in which you want to get the result, currently this function supports
174
     * text/turtle, application/rdf+xml and application/json
175
     * @return string RDF data in the requested serialization
176
     */
177
    public function getRDF($vocid, $uri, $format)
178
    {
179
180
        if ($format == 'text/turtle') {
181
            $retform = 'turtle';
182
            $serialiser = new EasyRdf\Serialiser\Turtle();
183
        } elseif ($format == 'application/ld+json' || $format == 'application/json') {
184
            $retform = 'jsonld'; // serve JSON-LD for both JSON-LD and plain JSON requests
185
            $serialiser = new EasyRdf\Serialiser\JsonLd();
186
        } else {
187
            $retform = 'rdfxml';
188
            $serialiser = new EasyRdf\Serialiser\RdfXml();
189
        }
190
191
        if ($vocid !== null) {
0 ignored issues
show
introduced by
The condition $vocid !== null is always true.
Loading history...
192
            $vocab = $this->getVocabulary($vocid);
193
            $sparql = $vocab->getSparql();
194
            $arrayClass = $vocab->getConfig()->getArrayClassURI();
195
            $vocabs = array($vocab);
196
        } else {
197
            $sparql = $this->getDefaultSparql();
198
            $arrayClass = null;
199
            $vocabs = null;
200
        }
201
        $result = $sparql->queryConceptInfoGraph($uri, $arrayClass, $vocabs);
202
203
        if (!$result->isEmpty()) {
204
            return $serialiser->serialise($result, $retform);
205
        }
206
        return "";
207
    }
208
209
    /**
210
     * Makes a SPARQL-query to the endpoint that retrieves concept
211
     * references as it's search results.
212
     * @param ConceptSearchParameters $params an object that contains all the parameters needed for the search
213
     * @return array search results
214
     */
215
    public function searchConcepts($params)
216
    {
217
        // don't even try to search for empty prefix if no other search criteria (group or parent concept) has been set
218
        if (($params->getSearchTerm() === "" || !preg_match('/[^*]/', $params->getSearchTerm())) && !$params->getGroupLimit() && !$params->getParentLimit()) {
219
            return array();
220
        }
221
222
        $vocabs = $params->getVocabs();
223
        $showDeprecated=false;
224
        if (sizeof($vocabs) === 1) { // search within vocabulary
225
            $voc = $vocabs[0];
226
            $sparql = $voc->getSparql();
227
            $showDeprecated=$voc->getConfig()->getShowDeprecated();
228
        } else { // multi-vocabulary or global search
229
            $voc = null;
230
            $sparql = $this->getDefaultSparql();
231
            // @TODO : in a global search showDeprecated will always be false and cannot be set globally
232
        }
233
234
        $results = $sparql->queryConcepts($vocabs, $params->getAdditionalFields(), $params->getUnique(), $params,$showDeprecated);
235
        if ($params->getRest() && $results && $params->getSearchLimit() !== 0) {
236
          $results = array_slice($results, $params->getOffset(), $params->getSearchLimit());
237
        }
238
        $ret = array();
239
240
        foreach ($results as $hit) {
241
            if (sizeof($vocabs) == 1) {
242
                $hitvoc = $voc;
243
                $hit['vocab'] = $vocabs[0]->getId();
244
            } else {
245
                try {
246
                    $hitvoc = $this->getVocabularyByGraph($hit['graph']);
247
                    $hit['vocab'] = $hitvoc->getId();
248
                } catch (ValueError $e) {
249
                    trigger_error($e->getMessage(), E_USER_WARNING);
250
                    $hitvoc = null;
251
                    $hit['vocab'] = "???";
252
                }
253
            }
254
            unset($hit['graph']);
255
256
            $hit['voc'] = $hitvoc;
257
258
            if ($hitvoc === null || !$hitvoc->containsURI($hit['uri'])) {
259
                // if uri is a external vocab uri that is included in the current vocab
260
                $realvoc = $this->guessVocabularyFromURI($hit['uri'], $voc !== null ? $voc->getId() : null);
261
                if ($realvoc !== $hitvoc) {
262
                    unset($hit['localname']);
263
                    $hit['exvocab'] = ($realvoc !== null) ? $realvoc->getId() : "???";
264
                }
265
            }
266
267
            $ret[] = $hit;
268
        }
269
270
        return $ret;
271
    }
272
273
    /**
274
     * Function for performing a search for concepts and their data fields.
275
     * @param ConceptSearchParameters $params an object that contains all the parameters needed for the search
276
     * @return array array with keys 'count' and 'results'
277
     */
278
    public function searchConceptsAndInfo($params)
279
    {
280
        $params->setUnique(true);
281
        $allhits = $this->searchConcepts($params);
282
        $count = sizeof($allhits);
283
        $hits = array_slice($allhits, $params->getOffset(), $params->getSearchLimit());
284
285
        $ret = array();
286
        $uris = array();
287
        $vocabs = array();
288
        $uniqueVocabs = array();
289
        foreach ($hits as $hit) {
290
            $uniqueVocabs[$hit['voc']->getId()] = $hit['voc']->getId();
291
            $vocabs[] = $hit['voc'];
292
            $uris[] = $hit['uri'];
293
        }
294
        if (sizeof($uniqueVocabs) == 1) {
295
            $voc = $vocabs[0];
296
            $sparql = $voc->getSparql();
297
            $arrayClass = $voc->getConfig()->getArrayClassURI();
298
        } else {
299
            $arrayClass = null;
300
            $sparql = $this->getDefaultSparql();
301
        }
302
        if (sizeof($uris) > 0) {
303
            $ret = $sparql->queryConceptInfo($uris, $arrayClass, $vocabs, $params->getSearchLang());
304
        }
305
306
        // For marking that the concept has been found through an alternative label, hidden
307
        // label or a label in another language
308
        foreach ($hits as $idx => $hit) {
309
            if (isset($hit['altLabel']) && isset($ret[$idx])) {
310
                $ret[$idx]->setFoundBy($hit['altLabel'], 'alt');
311
            }
312
313
            if (isset($hit['hiddenLabel']) && isset($ret[$idx])) {
314
                $ret[$idx]->setFoundBy($hit['hiddenLabel'], 'hidden');
315
            }
316
317
            if (isset($hit['matchedPrefLabel'])) {
318
                $ret[$idx]->setFoundBy($hit['matchedPrefLabel'], 'lang');
319
            }
320
321
            if ($ret[$idx] && isset($hit['lang'])) {
322
                $ret[$idx]->setContentLang($hit['lang']);
323
            }
324
        }
325
326
        return array('count' => $count, 'results' => $ret);
327
    }
328
329
    /**
330
     * Creates dataobjects from an input array.
331
     * @param string $class the type of class eg. 'Vocabulary'.
332
     * @param array $resarr contains the EasyRdf\Resources.
333
     */
334
    private function createDataObjects($class, $resarr)
335
    {
336
        $ret = array();
337
        foreach ($resarr as $res) {
338
            $ret[] = new $class($this, $res);
339
        }
340
341
        return $ret;
342
    }
343
344
    /**
345
     * Returns the cached vocabularies.
346
     * @return array of Vocabulary dataobjects
347
     */
348
    public function getVocabularies()
349
    {
350
        if ($this->allVocabularies === null) { // initialize cache
351
            $vocs = $this->globalConfig->getGraph()->allOfType('skosmos:Vocabulary');
352
            $this->allVocabularies = $this->createDataObjects("Vocabulary", $vocs);
353
            foreach ($this->allVocabularies as $voc) {
354
                // register vocabulary ids as RDF namespace prefixes
355
                $prefix = preg_replace('/\W+/', '', $voc->getId()); // strip non-word characters
356
                try {
357
                    if ($prefix != '' && EasyRdf\RdfNamespace::get($prefix) === null) // if not already defined
358
                    {
359
                        EasyRdf\RdfNamespace::set($prefix, $voc->getUriSpace());
360
                    }
361
362
                } catch (Exception $e) {
363
                    // not valid as namespace identifier, ignore
364
                }
365
            }
366
        }
367
368
        return $this->allVocabularies;
369
    }
370
371
    /**
372
     * Returns the cached vocabularies from a category.
373
     * @param EasyRdf\Resource $cat the category in question
374
     * @return array of vocabulary dataobjects
375
     */
376
    public function getVocabulariesInCategory($cat)
377
    {
378
        $vocs = $this->globalConfig->getGraph()->resourcesMatching('dc:subject', $cat);
379
        return $this->createDataObjects("Vocabulary", $vocs);
380
    }
381
382
    /**
383
     * Creates dataobjects of all the different vocabulary categories (Health etc.).
384
     * @return array of Dataobjects of the type VocabularyCategory.
385
     */
386
    public function getVocabularyCategories()
387
    {
388
        $cats = $this->globalConfig->getGraph()->allOfType('skos:Concept');
389
        if(empty($cats)) {
390
            return array(new VocabularyCategory($this, null));
391
        }
392
393
        return $this->createDataObjects("VocabularyCategory", $cats);
394
    }
395
396
    /**
397
     * Returns the label defined in config.ttl with the appropriate language.
398
     * @param string $lang language code of returned labels, eg. 'fi'
399
     * @return string the label for vocabulary categories.
400
     */
401
    public function getClassificationLabel($lang)
402
    {
403
        $cats = $this->globalConfig->getGraph()->allOfType('skos:ConceptScheme');
404
        return $cats ? $cats[0]->label($lang) : null;
0 ignored issues
show
Bug introduced by
The method label() does not exist on EasyRdf\Literal. ( Ignorable by Annotation )

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

404
        return $cats ? $cats[0]->/** @scrutinizer ignore-call */ label($lang) : null;

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method label() does not exist on null. ( Ignorable by Annotation )

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

404
        return $cats ? $cats[0]->/** @scrutinizer ignore-call */ label($lang) : null;

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
405
    }
406
407
    /**
408
     * Returns a single cached vocabulary.
409
     * @param string $vocid the vocabulary id eg. 'mesh'.
410
     * @return Vocabulary dataobject
411
     */
412
    public function getVocabulary($vocid): Vocabulary
413
    {
414
        $vocs = $this->getVocabularies();
415
        foreach ($vocs as $voc) {
416
            if ($voc->getId() == $vocid) {
417
                return $voc;
418
            }
419
        }
420
        throw new ValueError("Vocabulary id '$vocid' not found in configuration.");
421
    }
422
423
    /**
424
     * Return the vocabulary that is stored in the given graph on the given endpoint.
425
     *
426
     * @param $graph string graph URI
427
     * @param $endpoint string endpoint URL (default SPARQL endpoint if omitted)
428
     * @return Vocabulary vocabulary of this URI, or null if not found
429
     */
430
    public function getVocabularyByGraph($graph, $endpoint = null)
431
    {
432
        if ($endpoint === null) {
433
            $endpoint = $this->getConfig()->getDefaultEndpoint();
434
        }
435
        if ($this->vocabsByGraph === null) { // initialize cache
436
            $this->vocabsByGraph = array();
437
            foreach ($this->getVocabularies() as $voc) {
438
                $key = json_encode(array($voc->getGraph(), $voc->getEndpoint()));
439
                $this->vocabsByGraph[$key] = $voc;
440
            }
441
        }
442
443
        $key = json_encode(array($graph, $endpoint));
444
        if (array_key_exists($key, $this->vocabsByGraph)) {
445
            return $this->vocabsByGraph[$key];
446
        } else {
447
            throw new ValueError("no vocabulary found for graph $graph and endpoint $endpoint");
448
        }
449
450
    }
451
452
    /**
453
     * When multiple vocabularies share same URI namespace, return the
454
     * vocabulary in which the URI is actually defined (has a label).
455
     *
456
     * @param Vocabulary[] $vocabs vocabularies to search
457
     * @param string $uri URI to look for
458
     * @param $preferredVocabId string ID of the preferred vocabulary to return if more than one is found
459
     * @return Vocabulary the vocabulary with the URI
460
     */
461
462
    private function disambiguateVocabulary($vocabs, $uri, $preferredVocabId = null)
463
    {
464
        // if there is only one candidate vocabulary, return it
465
        if (sizeof($vocabs) == 1) {
466
            return $vocabs[0];
467
        }
468
469
        // if there are multiple vocabularies and one is the preferred vocabulary, return it
470
        if($preferredVocabId != null) {
471
            foreach ($vocabs as $vocab) {
472
                if($vocab->getId() == $preferredVocabId) {
473
                    try {
474
                        // double check that a label exists in the preferred vocabulary
475
                        if ($vocab->getConceptLabel($uri, null) !== null) {
476
                            return $vocab;
477
                        } else {
478
                            // not found in preferred vocabulary, fall back to next method
479
                            break;
480
                        }
481
                    } catch (EasyRdf\Http\Exception | EasyRdf\Exception | Throwable $e) {
0 ignored issues
show
Bug introduced by
The type  EasyRdf\Exception was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
482
                        if ($this->getConfig()->getLogCaughtExceptions()) {
483
                            error_log('Caught exception: ' . $e->getMessage());
484
                        }
485
                        break;
486
                    }
487
                }
488
            }
489
        }
490
491
        // no preferred vocabulary, or it was not found, search in which vocabulary the concept has a label
492
        foreach ($vocabs as $vocab) {
493
            try {
494
                if ($vocab->getConceptLabel($uri, null) !== null) {
495
                    return $vocab;
496
                }
497
            } catch (EasyRdf\Http\Exception | EasyRdf\Exception | Throwable $e) {
498
                if ($this->getConfig()->getLogCaughtExceptions()) {
499
                    error_log('Caught exception: ' . $e->getMessage());
500
                }
501
                break;
502
            }
503
        }
504
505
        // if the URI couldn't be found, fall back to the first vocabulary
506
        return $vocabs[0];
507
    }
508
509
    /**
510
     * Guess which vocabulary a URI originates from, based on the declared
511
     * vocabulary URI spaces.
512
     *
513
     * @param $uri string URI to search
514
     * @param $preferredVocabId string ID of the preferred vocabulary to return if more than one is found
515
     * @return Vocabulary vocabulary of this URI, or null if not found
516
     */
517
    public function guessVocabularyFromURI($uri, $preferredVocabId = null)
518
    {
519
        if ($this->vocabsByUriSpace === null) { // initialize cache
520
            $this->vocabsByUriSpace = array();
521
            foreach ($this->getVocabularies() as $voc) {
522
                $this->vocabsByUriSpace[$voc->getUriSpace()][] = $voc;
523
            }
524
        }
525
526
        // try to guess the URI space and look it up in the cache
527
        $res = new EasyRdf\Resource($uri);
528
        $namespace = substr($uri, 0, -strlen($res->localName()));
529
        if (array_key_exists($namespace, $this->vocabsByUriSpace)) {
530
            $vocabs = $this->vocabsByUriSpace[$namespace];
531
            return $this->disambiguateVocabulary($vocabs, $uri, $preferredVocabId);
532
        }
533
534
        // didn't work, try to match with each URI space separately
535
        foreach ($this->vocabsByUriSpace as $urispace => $vocabs) {
536
            if (strpos($uri, $urispace) === 0) {
537
                return $this->disambiguateVocabulary($vocabs, $uri, $preferredVocabId);
538
            }
539
        }
540
541
        // not found
542
        return null;
543
    }
544
545
    /**
546
     * Get the label for a resource, preferring 1. the given language 2. configured languages 3. any language.
547
     * @param EasyRdf\Resource $res resource whose label to return
548
     * @param string $lang preferred language
549
     * @return EasyRdf\Literal label as an EasyRdf\Literal object, or null if not found
550
     */
551
    public function getResourceLabel($res, $lang)
552
    {
553
        $langs = array_merge(array($lang), array_keys($this->getConfig()->getLanguages()));
554
        foreach ($langs as $l) {
555
            $label = $res->label($l);
556
            if ($label !== null) {
557
                return $label;
558
            }
559
560
        }
561
        return $res->label(); // desperate check for label in any language; will return null if even this fails
562
    }
563
564
    public function getResourceFromUri($uri)
565
    {
566
        // using apc cache for the resource if available
567
        if ($this->globalConfig->getCache()->isAvailable()) {
568
            // @codeCoverageIgnoreStart
569
            $key = 'fetch: ' . $uri;
570
            $resource = $this->globalConfig->getCache()->fetch($key);
571
            if ($resource === null || $resource === false) { // was not found in cache, or previous request failed
572
                $resource = $this->resolver->resolve($uri, $this->getConfig()->getHttpTimeout());
573
                $this->globalConfig->getCache()->store($key, $resource, self::URI_FETCH_TTL);
574
            }
575
            // @codeCoverageIgnoreEnd
576
        } else { // APC not available, parse on every request
577
            $resource = $this->resolver->resolve($uri, $this->getConfig()->getHttpTimeout());
578
        }
579
        return $resource;
580
    }
581
582
    /**
583
     * Returns a SPARQL endpoint object.
584
     * @param string $dialect eg. 'JenaText'.
585
     * @param string $endpoint url address of endpoint
586
     * @param string|null $graph uri for the target graph.
587
     */
588
    public function getSparqlImplementation($dialect, $endpoint, $graph)
589
    {
590
        $classname = $dialect . "Sparql";
591
592
        return new $classname($endpoint, $graph, $this);
593
    }
594
595
    /**
596
     * Returns a SPARQL endpoint object using the default implementation set in the config.ttl.
597
     */
598
    public function getDefaultSparql()
599
    {
600
        return $this->getSparqlImplementation($this->getConfig()->getDefaultSparqlDialect(), $this->getConfig()->getDefaultEndpoint(), '?graph');
601
    }
602
603
}
604