<?php
namespace CorpusParole\Models;
use Config;
use CorpusParole\Libraries\Utils;
use CorpusParole\Libraries\CocoonUtils;
use CorpusParole\Libraries\RdfModel\RdfModelResource;
use JsonSerializable;
use Log;
use EasyRdf\Literal;
use EasyRdf\Resource;
use EasyRdf\Graph;
use EasyRdf\Isomorphic;
/**
* Model class for Document. Inherit from EasyRd\Resource
* SELECT DISTINCT ?g WHERE {GRAPH ?g {?s ?p ?o}}
*/
class Document extends DocumentBase {
public function __construct($uri, $graph = null) {
// print($graph->dump('html'));
parent::__construct($uri, $graph);
}
private $publishers = null;
private $mediaArray = null;
private $transcript = false;
private $contributors = null;
private $subjects = null;
private $types = null;
private $descriptions = null;
private $geoInfo = false;
private $alternativeTitle = false;
private $rights = false;
protected function clearMemoizationCache() {
parent::clearMemoizationCache();
$this->publishers = null;
$this->mediaArray = null;
$this->contributors = null;
$this->subjects = null;
$this->types = null;
$this->descriptions = null;
$this->transcript = false;
$this->geoInfo = false;
$this->rights = false;
}
protected function additionalDeltaLists() {
$geoInfo = $this->getGeoInfo();
$geoInfoDeltas = is_null($geoInfo)?[]:$geoInfo->getDeltaList();
return empty($geoInfoDeltas)?[]:[$geoInfoDeltas,];
}
private function parseWebResources() {
$this->mediaArray = [];
$this->transcript = null;
$master = $this->get('<http://www.europeana.eu/schemas/edm/isShownBy>');
$masterUrl = is_null($master)?null:$master->getUri();
foreach($this->graph->allOfType("<http://www.europeana.eu/schemas/edm/WebResource>") as $webResource) {
$formatLit = $webResource->getLiteral("dc11:format");
$format = is_null($formatLit)?null:$formatLit->getValue();
if(is_null($format)) {
throw new ModelsException("parseWebResources: No dc:11 format on web resource");
}
if(0 === strpos($format, 'audio/') ||
0 === strpos($format, 'video/') ||
0 === strpos($format, 'Sampling:') ) {
array_push(
$this->mediaArray,
new MediaResource(
$webResource->getUri(),
$this->graph,
(($webResource->getUri() === $masterUrl)?true:false))
);
} else if(
0 === strpos($format, 'application/xml') ||
0 === strpos($format, 'application/pdf') ) {
$this->transcript = new TranscriptResource($webResource->getUri(), $this->graph);
}
else {
throw new ModelsException("parseWebResources: unknown format");
}
}
}
public function getMediaArray() {
if(is_null($this->mediaArray)) {
$this->parseWebResources();
}
return $this->mediaArray;
}
public function getTypes() {
if(is_null($this->types)) {
$this->types = $this->getProvidedCHO()->all('dc11:type');
}
return $this->types;
}
public function getDiscourseTypes() {
return array_values(array_filter($this->getTypes(), function($v) {
return $v instanceof Resource
&& preg_match(config('corpusparole.bnf_ark_url_regexp'), $v->getUri())
&& array_key_exists($v->getUri(), config('corpusparole.corpus_discourse_type'));
}));
}
public function getOtherTypes() {
$res = array_values(array_filter($this->getTypes(), function($v) {
return !($v instanceof Resource)
|| !preg_match(config('corpusparole.bnf_ark_url_regexp'), $v->getUri())
|| !array_key_exists($v->getUri(), config('corpusparole.corpus_discourse_type'));
}));
return $res;
}
public function getTranscript() {
if($this->transcript === false) {
$this->parseWebResources();
}
return $this->transcript;
}
public function getContributors() {
if(is_null($this->contributors)) {
$roleList = CocoonUtils::OLAC_ROLES;
array_push($roleList, 'http://purl.org/dc/elements/1.1/creator');
$this->contributors = array_reduce(
$roleList,
function($res, $olacRole) {
return array_merge(
$res,
array_map(
function($olacValue) use ($olacRole) {
return [
'name' => ($olacValue instanceof Literal)?$olacValue->getValue():null,
'nameLiteral' => ($olacValue instanceof Literal)?$olacValue:null,
'url' => ($olacValue instanceof Resource)?$olacValue->getUri():null,
'role' => $olacRole
];
},
$this->getProvidedCHO()->all("<$olacRole>")
)
);
},
[]
);
}
return $this->contributors;
}
/**
* change contributors list
*/
public function setContributors($contributors) {
$delta = $this->startDelta();
//remove old,
foreach ($this->getContributors() as $contribDef) {
$value = null;
if (empty($contribDef['url'])) {
if(empty($contribDef['nameLiteral'])) {
$value = new Literal($contribDef['name']);
} else {
$value = $contribDef['nameLiteral'];
}
} else {
$value = new Resource($contribDef['url']);
}
$this->getProvidedCHO()->delete($contribDef['role'], $value);
$delta->getDeletedGraph()->add($this->getProvidedCHO(), $contribDef['role'], $value);
}
//put new
foreach ($contributors as $newContribDef) {
$value = null;
if (empty($newContribDef['url'])) {
$value = new Literal($newContribDef['name'], "fr", null);
} else {
$value = new Resource($newContribDef['url']);
}
$this->getProvidedCHO()->add($newContribDef['role'], $value);
$delta->getAddedGraph()->add($this->getProvidedCHO(), $newContribDef['role'], $value);
}
$this->contributors = null;
}
/**
* change discourse type list
*/
public function updateDiscourseTypes(array $discoursesTypes) {
$this->startDelta();
//delete
foreach($this->getDiscourseTypes() as $discourseType) {
$this->getProvidedCHO()->delete('dc11:type', $discourseType);
$this->currentDelta->getDeletedGraph()->addResource($this->getProvidedCHO(), 'dc11:type', $discourseType->getUri());
}
// and re-add them
foreach($discoursesTypes as $dType) {
$this->getProvidedCHO()->addResource('dc11:type', $dType);
$this->currentDelta->getAddedGraph()->addResource($this->getProvidedCHO(), 'dc11:type', $dType);
}
$this->clearMemoizationCache();
}
/**
* Get subjects list
*/
public function getSubjects() {
if(is_null($this->subjects)) {
$this->subjects = $this->getProvidedCHO()->all('<http://purl.org/dc/elements/1.1/subject>');
}
return $this->subjects;
}
/**
* get the GeoInfoObject
* Ths returned object should be limited for read only activities.
* If it needs to be edited use the addGeoInfo method.
*/
public function getGeoInfo() {
if($this->geoInfo === false) {
$places = $this->getProvidedCHO()->all('<http://purl.org/dc/terms/spatial>');
$this->geoInfo = null;
if($places) {
$this->geoInfo = new GeoResource($places[0]->getUri(), $this->graph, $this->getProvidedCHO());
}
}
return $this->geoInfo;
}
public function addGeoInfo() {
$geoInfo = $this->getGeoInfo();
if(!is_null($geoInfo)) {
// if there already is a geo info, just return it.
$geoInfo->setReadOnly(false);
$geoInfo->setNeedDelete(true);
return $geoInfo;
}
$this->geoInfo = false;
$geoinfoNode = $this->getGraph()->newBNode("http://www.europeana.eu/schemas/edm/Place");
$this->getProvidedCHO()->addResource("http://purl.org/dc/terms/spatial", $geoinfoNode);
$this->geoInfo = new GeoResource($geoinfoNode->getUri(), $this->graph, $this->getProvidedCHO());
$this->geoInfo->setReadOnly(false);
$this->geoInfo->setNeedDelete(false);
return $this->geoInfo;
}
/**
* change subjecs list
*/
public function setSubjects($subjects) {
$delta = $this->startDelta();
//remove old,
foreach ($this->getSubjects() as $subject) {
$this->getProvidedCHO()->delete('<http://purl.org/dc/elements/1.1/subject>', $subject);
$delta->getDeletedGraph()->add($this->getProvidedCHO(), 'http://purl.org/dc/elements/1.1/subject', $subject);
}
//put new
foreach ($subjects as $newSubject) {
$value = null;
if(is_string($newSubject) && filter_var($newSubject, FILTER_VALIDATE_URL)) {
$value = new Resource($newSubject);
}
elseif (is_string($newSubject)) {
$value = new Literal($newSubject, null, null);
} elseif(is_array($newSubject)) {
$value = new Literal(isset($newSubject['value'])?$newSubject['value']:null, isset($newSubject['lang'])?$newSubject['lang']:null, isset($newSubject['datatype'])?$newSubject['value']:null);
}
$this->getProvidedCHO()->add('http://purl.org/dc/elements/1.1/subject', $value);
$delta->getAddedGraph()->add($this->getProvidedCHO(), 'http://purl.org/dc/elements/1.1/subject', $value);
}
$this->subjects = null;
}
public function getPublishers() {
if(is_null($this->publishers)) {
try {
$this->publishers = $this->getProvidedCHO()->all('dc11:publisher');
} catch(\Exception $e) {
$this->publishers = [];
}
}
return $this->publishers;
}
public function getPublishersValues() {
$publishers = $this->getPublishers();
return array_map(
function($v) { return Utils::processLiteralResourceOrString($v); },
$this->getPublishers()
);
}
/**
* Get descriptions
*/
public function getDescriptions() {
if(is_null($this->descriptions)) {
$this->descriptions = [];
$this->descriptions = array_merge($this->descriptions, $this->getProvidedCHO()->all('<http://purl.org/dc/elements/1.1/description>'));
$this->descriptions = array_merge($this->descriptions, $this->getProvidedCHO()->all('<http://purl.org/dc/terms/abstract>'));
$this->descriptions = array_merge($this->descriptions, $this->getProvidedCHO()->all('<http://purl.org/dc/terms/tableOfContents>'));
}
return $this->descriptions;
}
/**
* Get Alternative Title
*/
public function getAlternativeTitle() {
if($this->alternativeTitle === false) {
try {
$this->alternativeTitle = $this->getProvidedCHO()->getLiteral('<http://purl.org/dc/terms/alternative>');
} catch(\Exception $e) {
$this->alternativeTitle = null;
}
}
return $this->alternativeTitle;
}
public function getAlternativeTitleValue() {
$alternativeTitle = $this->getAlternativeTitle();
return is_null($alternativeTitle)?null:$alternativeTitle->getValue();
}
/**
* Get Rights
*/
public function getRights() {
if($this->rights === false) {
try {
$this->rights = $this->getResource('<http://www.europeana.eu/schemas/edm/rights>');
} catch(\Exception $e) {
$this->rights = null;
}
}
return $this->rights;
}
public function getRightsValue() {
$rights = $this->getRights();
return is_null($rights)?null:$rights->getUri();
}
public function isIsomorphic($doc) {
return Isomorphic::isomorphic($this->graph, $doc->graph);
}
/*
* Clone document.
* clone also the innerDocumenent
*/
public function __clone() {
if(!is_null($this->graph)) {
$this->graph = new Graph($this->graph->getUri(), $this->graph->toRdfPhp());
}
}
public function jsonSerialize() {
$res = parent::jsonSerialize();
if($this->graph) {
$mediaArray = is_null($this->getMediaArray())?
null:
array_combine(
array_map(function($m) { return $m->getUrl(); }, $this->getMediaArray()),
array_map(
function($m) {
return $m->jsonSerialize();},
$this->getMediaArray()
)
);
$transcript = is_null($this->getTranscript())?null:$this->getTranscript()->jsonSerialize();
$geoInfo = is_null($this->getGeoInfo())?null:$this->getGeoInfo()->jsonSerialize();
$publishers = $this->getPublishersValues();
$contributors = array_map(
function($c) { unset($c['nameLiteral']); return $c; },
$this->getContributors()
);
$subjects = array_map(
function($s) { return Utils::processLiteralResourceOrString($s); },
$this->getSubjects()
);
$types = array_map(
function($s) { return Utils::processLiteralResourceOrString($s); },
$this->getTypes()
);
$descriptions = array_map(
function($s) { return Utils::processLiteralResourceOrString($s); },
$this->getDescriptions()
);
$res = array_merge($res, [
'publishers' => $publishers,
'contributors' => $contributors,
'subjects' => $subjects,
'types' => $types,
'transcript' => $transcript,
'mediaArray'=> $mediaArray,
'geoInfo' => $geoInfo,
'descriptions' => $descriptions,
'alternativeTitle' => $this->getAlternativeTitleValue(),
'rights' => $this->getRightsValue()
]);
}
return $res;
}
}