Repository navigation
Problem: SKOS import fatals with "Call to a member function getValue() on null" when skos:related points at a concept that was not imported #2417
Copy link
Copy link
Closed as not planned
Closed as not planned
Copy link
Labels
Type: bugA flaw in the code that causes the software to produce an incorrect or unexpected result.A flaw in the code that causes the software to produce an incorrect or unexpected result.
Description
Current Behavior
sfSkosPlugin::importGraph() runs two passes that disagree about which concepts exist, and the mismatch is fatal.
Pass one imports concepts and stamps each with atom:id:
$concepts = $this->getRootConcepts();
foreach ($concepts as $item) {
...
$this->addConcept($item, $this->parent->id);
}
addConcept() sets the stamp and recurses through skos:narrower only:
$concept->set('atom:id', (int) $term->id);
foreach ($concept->allResources('skos:narrower') as $item) {
$this->addConcept($item, $term->id);
}
Pass two walks every concept in the graph and dereferences that stamp on both ends of every skos:related, unguarded (line 113):
foreach ($this->graph->allOfType('skos:Concept') as $c) {
foreach ($c->allResources('skos:related') as $r) {
$relations->insert($c->get('atom:id')->getValue(), $r->get('atom:id')->getValue());
}
}
Pass one visits only what is reachable from a root via skos:narrower; pass two visits everything. Any concept in the second set but not the first has no atom:id, get() returns null, and getValue() is a fatal.
getRootConcepts() is what makes this easy to hit:
$conceptScheme = $this->graph->get('skos:ConceptScheme', '^rdf:type');
if (null !== $conceptScheme) {
$topConcepts = $conceptScheme->allResources('skos:hasTopConcept');
if (0 < count($topConcepts)) {
return $topConcepts;
}
}
return $this->graph->allOfType('skos:Concept');
### Expected Behavior
1. Save this as sample.ttl:
turtle
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix ex: <http://example.org/> .
ex:scheme a skos:ConceptScheme ;
skos:hasTopConcept ex:a .
ex:a a skos:Concept ;
skos:prefLabel "Imported"@en ;
skos:related ex:b .
ex:b a skos:Concept ;
skos:prefLabel "Never imported"@en .
2. Import it into any taxonomy (Manage > Taxonomies > Import, or the XML import).
3. ex:a is created, then the job ends in Error.
ex:b is a skos:Concept, so pass two sees it; it is neither a top concept nor skos:narrower of one, so pass one never stamps it.
Job report from the original report (a 10-concept Places file):
[info] Importing SKOS file: sample_skos.ttl
[info] Type of scheme: file
[info] Taxonomy: Places
[info] Term ID: 110
[info] The graph contains 10 concepts.
[err] Exception: Call to a member function getValue() on null
[err] File: plugins/sfSkosPlugin/lib/sfSkosPlugin.class.php
[err] Line: 113
**Expected Behavior**
```markdown
The import completes, creating the concepts it can and skipping only the relation it cannot express — with a line in the job log naming the concepts involved, so the cataloguer can see what was dropped and why.
A `skos:related` naming a concept outside the imported set is ordinary, valid SKOS. It should not be able to end the run.
Two things make the current behaviour worse than a simple failure:
- **The partial import persists.** Terms created before the fatal are already saved, so a re-run duplicates them and the file cannot simply be re-imported after a fix.
- **The error names no concept.** It reports a file and a line, so there is nothing to point the cataloguer at in a 10-concept file, let alone a large vocabulary.
### Possible Solution
```php
foreach ($this->graph->allOfType('skos:Concept') as $c) {
foreach ($c->allResources('skos:related') as $r) {
$subject = $c->get('atom:id');
$object = $r->get('atom:id');
if (null === $subject || null === $object) {
$this->logger->info($this->i18n->__(
'Skipping skos:related between %1% and %2%: one of them was not imported.',
['%1%' => $c->getUri(), '%2%' => $r->getUri()]
));
continue;
}
$relations->insert($subject->getValue(), $object->getValue());
}
}
### Context and Notes
AtoM 2.10.1 and 2.10.2 (plugins/sfSkosPlugin/lib/sfSkosPlugin.class.php:113, unchanged between the two). PHP 8.3, MySQL 8, nginx, Ubuntu 22.04.
### Version used
2.10.1
### Operating System and version
22.04
### Default installation culture
en
### PHP version
8.3
### Contact details
johan@theahg.co.zaReactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Type: bugA flaw in the code that causes the software to produce an incorrect or unexpected result.A flaw in the code that causes the software to produce an incorrect or unexpected result.
Activity
johanpiet2 commentedon Oct 2, 2026
Duplicate of #2418, filed twice by mistake.