<?php
namespace CorpusParole\Services;
use Cache;
use CorpusParole\Services\BnfResolverInterface;
class BnfResolver implements BnfResolverInterface {
public function __construct($sparqlClient) {
$this->sparqlClient = $sparqlClient;
}
private function checkBnfId($id) {
$bnfid = $id;
if(strpos($id, config('corpusparole.bnf_ark_base_url')) === 0) {
$bnfid = config('corpusparole.bnf_base_url').substr($id, strlen(config('corpusparole.bnf_ark_base_url')));
}
elseif(strpos($id, config('corpusparole.bnf_base_url')) !== 0) {
$bnfid = config('corpusparole.bnf_base_url').$id;
}
$bnfid = rtrim($bnfid, '/');
if(preg_match("/^".preg_quote(config('corpusparole.bnf_base_url'),"/")."ark\:\/12148\/[[:alnum:]]/", $bnfid) !== 1) {
throw new BnfResolverException("the provided id \"$id\" is not a BNF id");
}
return $bnfid;
}
/**
* Get label from BNF id
* @param string $id The id to resolve. Can be an url starting with http://data.bnf.fr/ or http://ark.bnf.fr/
* @return a string with the name
*/
public function getLabel($id) {
$res = $this->getlabels([$id,]);
assert(array_key_exists($id,$res), "the result must contains $id");
return $res[$id];
}
/**
* Get a list of names from an array of viaf ids.
* @param array $ids The array of ids to resolve.
* Each id can be an url starting with http://data.bnf.fr/ or http://ark.bnf.fr/
*/
public function getLabels(array $ids) {
if(count($ids) > config('corpusparole.bnf_max_ids')) {
throw new BnfResolverException("Too manys ids provided");
}
$bnfids = array_map([$this, 'checkBnfId'], $ids);
$bnfidsMap = array_combine($bnfids, $ids);
$results = [];
$missingBnfids = [];
foreach ($bnfidsMap as $bnfid => $bnfidSource) {
$cachedValue = Cache::get("bnf:$bnfid");
if(is_null($cachedValue)) {
array_push($missingBnfids, $bnfid);
} else {
$results[$bnfidSource] = $cachedValue;
}
}
if(count($missingBnfids) == 0) {
return $results;
}
$query = "SELECT ?s ?o WHERE {";
foreach ($missingBnfids as $index => $bid) {
if($index > 0) {
$query .= " UNION ";
}
$query .= "{ <$bid> <http://www.w3.org/2004/02/skos/core#prefLabel> ?o. ?s <http://www.w3.org/2004/02/skos/core#prefLabel> ?o. FILTER(?s = <$bid> && lang(?o) = \"fr\")}";
}
$query .= "}";
$docs = $this->sparqlClient->query($query);
$resultsRaw = [];
foreach ($docs as $doc) {
$bnfid = $doc->s->getUri();
$bnflabel = $doc->o;
$value = $bnflabel->getValue();
if(!empty($value)) {
$resultsRaw[$bnfid] = $bnflabel;
}
}
foreach ($missingBnfids as $bnfid) {
$bnfidSource = $bnfidsMap[$bnfid];
$missingValue = (array_key_exists($bnfid,$resultsRaw) && $resultsRaw[$bnfid])?mb_strtolower($resultsRaw[$bnfid]->getValue()):"";
if (mb_strlen($missingValue)>0) {
Cache::put("bnf:$bnfid", $missingValue, config('corpusparole.bnf_cache_expiration'));
$results[$bnfidSource] = $missingValue;
}
else {
$results[$bnfidSource] = null;
}
}
return $results;
}
}