Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 355
0.00% covered (danger)
0.00%
0 / 26
CRAP
0.00% covered (danger)
0.00%
0 / 1
core_kernel_persistence_starsql_Resource
0.00% covered (danger)
0.00%
0 / 355
0.00% covered (danger)
0.00%
0 / 26
8190
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getModel
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPersistence
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getNewTripleModelId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTypes
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
6
 getPropertyValues
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 1
56
 getPropertyValuesByLg
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 setPropertyValue
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
56
 setPropertiesValues
0.00% covered (danger)
0.00%
0 / 66
0.00% covered (danger)
0.00%
0 / 1
380
 setPropertyValueByLg
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 removePropertyValues
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 1
110
 removePropertyValueByLg
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
6
 getRdfTriples
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
20
 isWritable
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getUsedLanguages
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
30
 duplicate
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 delete
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 getPropertiesValues
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 1
110
 setType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 removeType
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
2
 getServiceLocator
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDataLanguage
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDefaultLanguage
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLanguageProcessor
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 buildTriplesFromNode
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
30
 formatValue
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2023 (original work) Open Assessment Technologies SA ;
19 */
20
21declare(strict_types=1);
22
23use oat\generis\model\kernel\persistence\starsql\LanguageProcessor;
24use oat\generis\model\OntologyRdf;
25use oat\oatbox\session\SessionService;
26use oat\oatbox\user\UserLanguageServiceInterface;
27use WikibaseSolutions\CypherDSL\Clauses\SetClause;
28use Zend\ServiceManager\ServiceLocatorInterface;
29
30use function WikibaseSolutions\CypherDSL\node;
31use function WikibaseSolutions\CypherDSL\parameter;
32use function WikibaseSolutions\CypherDSL\procedure;
33use function WikibaseSolutions\CypherDSL\query;
34use function WikibaseSolutions\CypherDSL\raw;
35use function WikibaseSolutions\CypherDSL\relationshipTo;
36use function WikibaseSolutions\CypherDSL\variable;
37
38class core_kernel_persistence_starsql_Resource implements core_kernel_persistence_ResourceInterface
39{
40    /**
41     * @var core_kernel_persistence_starsql_StarModel
42     */
43    private $model;
44
45    public function __construct(core_kernel_persistence_starsql_StarModel $model)
46    {
47        $this->model = $model;
48    }
49
50    protected function getModel(): core_kernel_persistence_starsql_StarModel
51    {
52        return $this->model;
53    }
54
55    /**
56     * @return common_persistence_GraphPersistence
57     */
58    protected function getPersistence()
59    {
60        return $this->model->getPersistence();
61    }
62
63    protected function getNewTripleModelId()
64    {
65        return $this->model->getNewTripleModelId();
66    }
67
68    public function getTypes(core_kernel_classes_Resource $resource): array
69    {
70        $relatedResource = node();
71        $query = query()
72            ->match(
73                node()->withProperties(['uri' => $uriParameter = parameter()])
74                    ->withLabels(['Resource'])
75                    ->relationshipTo($relatedResource, OntologyRdf::RDF_TYPE)
76            )
77            ->returning($relatedResource->property('uri'))
78            ->build();
79
80        $results = $this->getPersistence()->run($query, [$uriParameter->getParameter() => $resource->getUri()]);
81        $returnValue = [];
82        foreach ($results as $result) {
83            $uri = $result->current();
84            $returnValue[$uri] = $this->getModel()->getClass($uri);
85        }
86
87        return (array) $returnValue;
88    }
89
90    public function getPropertyValues(
91        core_kernel_classes_Resource $resource,
92        core_kernel_classes_Property $property,
93        $options = []
94    ): array {
95        if (isset($options['last'])) {
96            throw new core_kernel_persistence_Exception('Option \'last\' no longer supported');
97        }
98
99        $node = node()
100            ->withProperties(['uri' => $uriParameter = parameter()])
101            ->withLabels(['Resource']);
102        if ($property->isRelationship()) {
103            $relationship = relationshipTo()->withTypes([$property->getUri()]);
104            $remoteNode = node();
105            $query = query()
106                ->match($node->relationship($relationship, $remoteNode))
107                ->returning($remoteNode->property('uri'));
108        } else {
109            $query = query()
110                ->match($node)
111                ->returning($node->property($property->getUri()));
112        }
113
114        $results = $this->getPersistence()->run(
115            $query->build(),
116            [$uriParameter->getParameter() => $resource->getUri()]
117        );
118        $values = [];
119        $selectedLanguage = $options['lg'] ?? null;
120        $dataLanguage = $this->getDataLanguage();
121        $defaultLanguage = $this->getDefaultLanguage();
122
123        foreach ($results as $result) {
124            $value = $result->current();
125            if ($value === null) {
126                continue;
127            }
128            if (is_iterable($value)) {
129                if (isset($selectedLanguage)) {
130                    $values = array_merge(
131                        $values,
132                        $this->getLanguageProcessor()->filterByLanguage($value, [$selectedLanguage])
133                    );
134                } else {
135                    $values = array_merge(
136                        $values,
137                        $this->getLanguageProcessor()->filterByAvailableLanguage(
138                            $value,
139                            $dataLanguage,
140                            $defaultLanguage
141                        )
142                    );
143                }
144            } else {
145                $values[] = $this->getLanguageProcessor()->parseTranslatedValue($value);
146            }
147        }
148
149        return $values;
150    }
151
152    public function getPropertyValuesByLg(
153        core_kernel_classes_Resource $resource,
154        core_kernel_classes_Property $property,
155        $lg
156    ): core_kernel_classes_ContainerCollection {
157        $options =  ['lg' => $lg];
158
159        $returnValue = new core_kernel_classes_ContainerCollection($resource);
160        foreach ($this->getPropertyValues($resource, $property, $options) as $value) {
161            $returnValue->add(common_Utils::toResource($value));
162        }
163
164        return $returnValue;
165    }
166
167    public function setPropertyValue(
168        core_kernel_classes_Resource $resource,
169        core_kernel_classes_Property $property,
170        $object,
171        $lg = null
172    ): ?bool {
173        $uri = $resource->getUri();
174        $propertyUri = $property->getUri();
175        if ($object instanceof core_kernel_classes_Resource) {
176            $object = $object->getUri();
177        } else {
178            $object = (string) $object;
179            if ($property->isLgDependent()) {
180                $lang = ((null != $lg)
181                    ? $lg
182                    : $this->getDataLanguage());
183                if (!empty($lang)) {
184                    $object .= '@' . $lang;
185                }
186            }
187        }
188        if ($property->isRelationship()) {
189            $query = <<<CYPHER
190                MATCH
191                  (a:Resource), (b:Resource)
192                WHERE a.uri = \$uri AND b.uri = \$object
193                CREATE (a)-[r:`{$propertyUri}`]->(b)
194                RETURN type(r)
195CYPHER;
196        } elseif ($property->isLgDependent()) {
197            $query = <<<CYPHER
198            MATCH (n:Resource {uri: \$uri})
199            SET n.`{$propertyUri}` = coalesce(n.`{$propertyUri}`, []) + \$object
200CYPHER;
201        } else {
202            $query = <<<CYPHER
203            MATCH (n:Resource {uri: \$uri})
204            SET n.`{$propertyUri}` = \$object
205CYPHER;
206        }
207        $this->getPersistence()->run($query, ['uri' => $uri, 'object' => $object]);
208
209        return true;
210    }
211
212    public function setPropertiesValues(core_kernel_classes_Resource $resource, $properties): ?bool
213    {
214        if (!is_array($properties) || count($properties) == 0) {
215            return false;
216        }
217
218        $parameters = [];
219        $node = node();
220        $node->addLabel('Resource');
221        $node->addProperty('uri', $uriParameter = parameter());
222        $parameters[$uriParameter->getParameter()] = $resource->getUri();
223
224        /** @var common_session_Session $session */
225        $session = $this->getServiceLocator()->get(SessionService::SERVICE_ID)->getCurrentSession();
226
227        $setClause = new SetClause();
228        $setClause->add(
229            $node->property('http://www.tao.lu/Ontologies/TAO.rdf#UpdatedBy')
230                ->replaceWith($authorParameter = parameter())
231        );
232        $parameters[$authorParameter->getParameter()] = (string)$session->getUser()->getIdentifier();
233        $setClause->add(
234            $node->property('http://www.tao.lu/Ontologies/TAO.rdf#UpdatedAt')
235                ->replaceWith(procedure()::raw('timestamp'))
236        );
237
238        $dataLanguage = $session->getDataLanguage();
239
240        $collectedProperties = [];
241        $collectedRelationships = [];
242        foreach ($properties as $propertyUri => $value) {
243            $property = $this->getModel()->getProperty($propertyUri);
244            $lang = ($property->isLgDependent() ? $dataLanguage : '');
245
246            if (!is_array($value)) {
247                $value = [$value];
248            }
249            foreach ($value as $val) {
250                // @TODO check if the property exists already
251                if ($val instanceof core_kernel_classes_Resource || $property->isRelationship()) {
252                    $valUri = $val instanceof core_kernel_classes_Resource ? $val->getUri() : $val;
253                    if (empty($valUri)) {
254                        continue;
255                    }
256                    $currentValues = $collectedRelationships[$valUri] ?? [];
257                    $collectedRelationships[$valUri] = array_merge($currentValues, [$propertyUri]);
258                } else {
259                    if ($lang) {
260                        $val .= '@' . $lang;
261                    }
262                    if (!empty($collectedProperties[$propertyUri])) {
263                        $currentValue = $collectedProperties[$propertyUri];
264                        if (is_array($currentValue)) {
265                            $collectedProperties[$propertyUri] = array_merge($currentValue, [$val]);
266                        } else {
267                            $collectedProperties[$propertyUri] = [$currentValue, $val];
268                        }
269                    } else {
270                        $collectedProperties[$propertyUri] = $val;
271                    }
272                }
273            }
274        }
275
276        foreach ($collectedProperties as $propUri => $values) {
277            $setClause->add($node->property($propUri)->replaceWith($propertyParameter = parameter()));
278            $parameters[$propertyParameter->getParameter()] = $values;
279        }
280        $relatedResources = [];
281        $merges = [];
282        $nodeCopy = node()->withVariable($node->getVariable());
283        foreach ($collectedRelationships as $target => $relationshipTypes) {
284            foreach ($relationshipTypes as $type) {
285                $variableForRelatedResource = variable();
286                $nodeForRelationship = node()->withVariable($variableForRelatedResource);
287                $relatedResource = node('Resource')
288                    ->withProperties(['uri' => $relatedUriParameter = parameter()])
289                    ->withVariable($variableForRelatedResource);
290                $parameters[$relatedUriParameter->getParameter()] = $target;
291                $merges[] = $nodeCopy->relationshipTo($nodeForRelationship, $type);
292                $relatedResources[] = $relatedResource;
293            }
294        }
295
296        $query = query();
297        foreach ($relatedResources as $relResource) {
298            $query->match($relResource);
299        }
300
301        $query->merge($node, $setClause, $setClause);
302        foreach ($merges as $mergeNode) {
303            $query->merge($mergeNode);
304        }
305
306        $query = $query->build();
307
308        $result = $this->getModel()->getPersistence()->run($query, $parameters);
309
310        return true;
311    }
312
313    public function setPropertyValueByLg(
314        core_kernel_classes_Resource $resource,
315        core_kernel_classes_Property $property,
316        $value,
317        $lg
318    ): ?bool {
319        return $this->setPropertyValue($resource, $property, $value, $lg);
320    }
321
322    public function removePropertyValues(
323        core_kernel_classes_Resource $resource,
324        core_kernel_classes_Property $property,
325        $options = []
326    ): ?bool {
327        $uri = $resource->getUri();
328        $propertyUri = $property->getUri();
329        $conditions = [];
330        $pattern = $options['pattern'] ?? null;
331        $isLike = !empty($options['like']);
332        if (!empty($pattern)) {
333            if (!is_array($pattern)) {
334                $pattern = [$pattern];
335            }
336
337            $multiCondition = "( ";
338            foreach ($pattern as $index => $token) {
339                if (empty($token)) {
340                    continue;
341                }
342                if ($index > 0) {
343                    $multiCondition .= ' OR ';
344                }
345                if ($isLike) {
346                    $multiCondition .= "n.`{$propertyUri}` =~ '" . str_replace('*', '.*', $token) . "'";
347                } else {
348                    $multiCondition .= "n.`{$propertyUri}` = '$token'";
349                }
350            }
351            $conditions[] = "{$multiCondition} ) ";
352        }
353
354        $assembledConditions = '';
355        foreach ($conditions as $i => $additionalCondition) {
356            if (empty($assembledConditions)) {
357                $assembledConditions .= " WHERE ( {$additionalCondition} ) ";
358            } else {
359                $assembledConditions .= " AND ( {$additionalCondition} ) ";
360            }
361        }
362
363        if (!$property->isRelationship()) {
364            $query = <<<CYPHER
365                MATCH (n:Resource {uri: "{$uri}"})
366                {$assembledConditions}
367                REMOVE n.`{$propertyUri}`
368                RETURN n
369CYPHER;
370        } else {
371            $query = <<<CYPHER
372                MATCH (n:Resource {uri: "{$uri}"})-[p:`{$propertyUri}`]->()
373                {$assembledConditions}
374                DELETE p
375                RETURN n
376CYPHER;
377        }
378
379        //@FIXME if value is array, then query should be for update. Try to deduce if $prop->isLgDependent or isMultiple
380        //@FIXME if property is represented as node relationship, query should remove that instead
381
382        $this->getPersistence()->run($query);
383
384        return true;
385    }
386
387    public function removePropertyValueByLg(
388        core_kernel_classes_Resource $resource,
389        core_kernel_classes_Property $property,
390        $lg,
391        $options = []
392    ): ?bool {
393        if (!$property->isLgDependent()) {
394            return $this->removePropertyValues($resource, $property, $options);
395        }
396
397        $node = node('Resource')->withProperties(['uri' => $uriParameter = parameter()]);
398        $property = $node->property($property->getUri());
399        $removeKeyProcedure = raw(sprintf(
400            "[item in %s WHERE NOT item ENDS WITH '@%s']",
401            $property->toQuery(),
402            $lg
403        ));
404
405        $query = query()
406            ->match($node)
407            ->where($property->isNotNull())
408            ->set($property->replaceWith($removeKeyProcedure))
409            ->build();
410
411        $this->getPersistence()->run($query, [$uriParameter->getParameter() => $resource->getUri()]);
412
413        return true;
414    }
415
416    public function getRdfTriples(core_kernel_classes_Resource $resource): core_kernel_classes_ContainerCollection
417    {
418        $relationship = relationshipTo()
419            ->withVariable($relationshipVar = variable())
420            ->withMinHops(0)
421            ->withMaxHops(1);
422        $relatedNode = node()->withLabels(['Resource'])->withVariable($relatedNodeVar = variable());
423        $node = node()->withProperties(['uri' => $uriParameter = parameter()])
424            ->withVariable($nodeVar = variable())
425            ->withLabels(['Resource'])
426            ->relationship($relationship, $relatedNode);
427        $query = query()
428            ->match($node)
429            ->returning([$nodeVar, $relatedNodeVar, $relationshipVar])
430            ->build();
431
432        $results = $this->getPersistence()->run($query, [$uriParameter->getParameter() => $resource->getUri()]);
433        $returnValue = new core_kernel_classes_ContainerCollection(new common_Object(__METHOD__));
434        $nodeProcessed = false;
435        foreach ($results as $result) {
436            $resultNode = $result->get($nodeVar->getName());
437            /** @var \Laudis\Neo4j\Types\CypherMap $resultRelationship */
438            $resultRelationship = $result->get($relationshipVar->getName());
439            $resultRelatedNode = $result->get($relatedNodeVar->getName());
440            if (!$nodeProcessed) {
441                $returnValue = $this->buildTriplesFromNode($returnValue, $resource->getUri(), $resultNode);
442                $nodeProcessed = true;
443            }
444            if (!$resultRelationship->isEmpty()) {
445                $resultRelationship = $resultRelationship->first();
446                $triple = new core_kernel_classes_Triple();
447                $triple->subject = $resource->getUri();
448                $triple->predicate = $resultRelationship->getType();
449                $triple->object = $resultRelatedNode->getProperty('uri');
450                $returnValue->add($triple);
451            }
452        }
453
454        return $returnValue;
455    }
456
457    public function isWritable(core_kernel_classes_Resource $resource): bool
458    {
459        return $this->model->isWritable($resource);
460    }
461
462    public function getUsedLanguages(
463        core_kernel_classes_Resource $resource,
464        core_kernel_classes_Property $property
465    ): array {
466        $node = node()->withProperties(['uri' => $uriParameter = parameter()])
467            ->withLabels(['Resource']);
468        $query = query()
469            ->match($node)
470            ->returning($node->property($property->getUri()))
471            ->build();
472
473        $results = $this->getPersistence()->run($query, [$uriParameter->getParameter() => $resource->getUri()]);
474        $foundLanguages = [];
475        foreach ($results as $result) {
476            $values = $result->current();
477            if (!is_iterable($values)) {
478                $values = [$values];
479            }
480            foreach ($values as $value) {
481                preg_match(LanguageProcessor::LANGUAGE_TAGGED_VALUE_PATTERN, $value, $matches);
482                if (isset($matches[2])) {
483                    $foundLanguages[] = $matches[2];
484                }
485            }
486        }
487
488        return (array) $foundLanguages;
489    }
490
491    public function duplicate(
492        core_kernel_classes_Resource $resource,
493        $excludedProperties = []
494    ): core_kernel_classes_Resource {
495        throw new common_Exception('Not implemented! ' . __FILE__ . ' line: ' . __LINE__);
496    }
497
498    public function delete(core_kernel_classes_Resource $resource, $deleteReference = false): ?bool
499    {
500        // @FIXME does $deleteReference still make sense? Since detach delete removes relationships as well?
501
502        $resourceNode = node()
503            ->withProperties(['uri' => $uriParameter = parameter()])
504            ->withLabels(['Resource']);
505        $query = query()
506            ->match($resourceNode)
507            ->detachDelete($resourceNode)
508            ->build();
509
510        $result = $this->getPersistence()->run($query, [$uriParameter->getParameter() => $resource->getUri()]);
511        // @FIXME handle failure, return false if no nodes/relationships affected
512
513        return true;
514    }
515
516    public function getPropertiesValues(core_kernel_classes_Resource $resource, $properties): array
517    {
518        if (count($properties) == 0) {
519            return [];
520        }
521
522        $query = <<<CYPHER
523            MATCH (resource:Resource)-[relationshipTo]->(relatedResource:Resource)
524            WHERE resource.uri = \$uri
525            RETURN resource,
526                collect({relationship: type(relationshipTo), relatedResourceUri: relatedResource.uri}) AS relationships
527CYPHER;
528
529        $results = $this->getPersistence()->run($query, ['uri' => $resource->getUri()]);
530        if ($results->isEmpty()) {
531            return [];
532        }
533        $result = $results->first();
534
535        $propertyUris = [];
536        foreach ($properties as $property) {
537            $uri = (is_string($property) ? $property : $property->getUri());
538            $propertyUris[] = $uri;
539            $returnValue[$uri] = [];
540        }
541        $dataLanguage = $this->getDataLanguage();
542        $defaultLanguage = $this->getDefaultLanguage();
543        foreach ($result->get('resource')->getProperties() as $key => $value) {
544            if (in_array($key, $propertyUris)) {
545                if (is_iterable($value)) {
546                    $returnValue[$key] =
547                        array_map(
548                            fn($value) => $this->formatValue($value),
549                            array_merge(
550                                $returnValue[$key] ?? [],
551                                $this->getLanguageProcessor()->filterByLanguage(
552                                    $value,
553                                    [$dataLanguage, $defaultLanguage]
554                                )
555                            )
556                        );
557                } else {
558                    $returnValue[$key][] = $this->formatValue(
559                        $value,
560                        [$this->getLanguageProcessor(), 'parseTranslatedValue']
561                    );
562                }
563            }
564        }
565        foreach ($result->get('relationships') as $relationship) {
566            if (in_array($relationship['relationship'], $propertyUris)) {
567                $returnValue[$relationship['relationship']][] = $this->formatValue($relationship['relatedResourceUri']);
568            }
569        }
570
571        return (array) $returnValue;
572    }
573
574    public function setType(core_kernel_classes_Resource $resource, core_kernel_classes_Class $class): ?bool
575    {
576        return $this->setPropertyValue($resource, $this->getModel()->getProperty(OntologyRdf::RDF_TYPE), $class);
577    }
578
579    public function removeType(core_kernel_classes_Resource $resource, core_kernel_classes_Class $class): ?bool
580    {
581        $typeRelationship = relationshipTo()->withTypes([OntologyRdf::RDF_TYPE]);
582        $classNode = node()->withProperties(['uri' => $classUriParameter = parameter()])
583            ->withLabels(['Resource']);
584        $node = node()->withProperties(['uri' => $uriParameter = parameter()])
585            ->withLabels(['Resource'])
586            ->relationship($typeRelationship, $classNode);
587        $query = query()
588            ->match($node)
589            ->delete($typeRelationship)
590            ->build();
591
592        $this->getPersistence()->run($query, [
593            $uriParameter->getParameter() => $resource->getUri(),
594            $classUriParameter->getParameter() => $class->getUri()
595        ]);
596
597        return true;
598    }
599
600    /**
601     * @return ServiceLocatorInterface
602     */
603    public function getServiceLocator()
604    {
605        return $this->getModel()->getServiceLocator();
606    }
607
608    protected function getDataLanguage()
609    {
610        return $this->getServiceLocator()->get(SessionService::SERVICE_ID)->getCurrentSession()->getDataLanguage();
611    }
612
613    protected function getDefaultLanguage()
614    {
615        return $this->getServiceLocator()->get(UserLanguageServiceInterface::SERVICE_ID)->getDefaultLanguage();
616    }
617
618    protected function getLanguageProcessor(): LanguageProcessor
619    {
620        return $this->getServiceLocator()->getContainer()->get(LanguageProcessor::class);
621    }
622
623    private function buildTriplesFromNode(core_kernel_classes_ContainerCollection $tripleCollection, $uri, $resultNode)
624    {
625        foreach ($resultNode->getProperties() as $propKey => $propValue) {
626            if ($propKey === 'uri') {
627                continue;
628            }
629            $triple = new core_kernel_classes_Triple();
630            $triple->subject = $uri;
631            $triple->predicate = $propKey;
632            if (is_iterable($propValue)) {
633                foreach ($propValue as $value) {
634                    $langTriple = clone $triple;
635                    $langTriple->lg = $this->getLanguageProcessor()->parseTranslatedLang($value);
636                    $langTriple->object = $this->getLanguageProcessor()->parseTranslatedValue($value);
637                    $tripleCollection->add($langTriple);
638                }
639            } else {
640                $triple->lg = $this->getLanguageProcessor()->parseTranslatedLang($propValue);
641                $triple->object = $this->getLanguageProcessor()->parseTranslatedValue($propValue);
642                $tripleCollection->add($triple);
643            }
644        }
645
646        return $tripleCollection;
647    }
648
649    private function formatValue($value, array $literalValueProcessingCallback = [])
650    {
651        return common_Utils::isUri($value) ?
652            $this->getModel()->getResource($value)
653            : new core_kernel_classes_Literal(
654                !empty($literalValueProcessingCallback)
655                    ? call_user_func($literalValueProcessingCallback, $value)
656                    : $value
657            );
658    }
659}