server/src/app/Models/Document.php
author ymh <ymh.work@gmail.com>
Wed, 03 Feb 2016 18:34:44 +0100
changeset 115 34ffc04cef62
parent 111 af85c436048f
child 122 b37fde30dd4a
permissions -rw-r--r--
add dc:identifier to providedCHO

<?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 RdfModelResource implements JsonSerializable {

    public function __construct($uri, $graph = null) {
        parent::__construct($uri, $graph);
    }

    private $id = null;

    // memoization
    private $providedCHO = null;
    private $title = false;
    private $lang = null;
    private $publishers = null;
    private $mediaArray = null;
    private $issued = null;
    private $modified = null;
    private $contributors = null;

    public function getProvidedCHO() {
        if(is_null($this->providedCHO)) {
            $this->providedCHO = $this->get("<http://www.europeana.eu/schemas/edm/aggregatedCHO>");
        }
        return $this->providedCHO;
    }

    private function clearMemoizationCache() {
        $this->providedCHO = null;
        $this->title = false;
        $this->lang = null;
        $this->publishers = null;
        $this->mediaArray = null;
        $this->issued = null;
        $this->modified = null;
        $this->contributors = null;
    }

    public function getId() {
        if(is_null($this->id)) {
            $this->id = $this->getProvidedCHO()->get('<http://purl.org/dc/terms/identifier>');
            if(is_null($this->id)) {
                $this->id = CocoonUtils::getIdFromCorpusUri($this->uri);
            }
        }
        return $this->id;
    }

    public function getLanguage() {
        if(is_null($this->lang)) {
            try {
                $langs = $this->getProvidedCHO()->all('<http://purl.org/dc/elements/1.1/language>');
                if(count($langs) > 0) {
                    $this->lang = $langs[0];
                }
            } catch(\Exception $e) {
                $this->lang = null;
            }
        }
        return $this->lang;
    }

    public function getLanguageValue() {
        $lang = $this->getLanguage();
        if($lang instanceof Resource) {
            return $lang->getUri();
        } else if($lan instanceof Literal) {
            return $lang->getValue();
        }
        return null;
    }

    public function getTitle() {
        if($this->title === false) {
            try {
                $this->title = $this->getProvidedCHO()->getLiteral('<http://purl.org/dc/elements/1.1/title>');
            } catch(\Exception $e) {
                $this->title = null;
            }
        }
        return $this->title;
    }

    public function setTitle($value, $lang="fr") {
        $oldTitle = $this->getTitle();
        if($oldTitle && $oldTitle->getValue() != $value && $oldTitle->getLang() != $lang) {
            $literalTitle = new Literal($value, $lang, null);
            $this->setSimpleProperty($this->getProvidedCHO(), 'http://purl.org/dc/elements/1.1/title', $oldTitle, $literalTitle);
            //clear cache
            $this->title = false;
        }
    }

    public function getTitleValue() {
        $title = $this->getTitle();
        return is_null($title)?null:$title->getValue();
    }

    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 getIssued() {
        if(is_null($this->issued)) {
            try {
                $this->issued = $this->getProvidedCHO()->getLiteral("<http://purl.org/dc/terms/issued>");
            } catch(\Exception $e) {
                $this->issued = null;
            }
        }
        return $this->issued;
    }

    public function getIssuedValue() {
        $issued = $this->getIssued();
        return is_null($issued)?null:$issued->getValue();
    }

    public function getModified() {
        if(is_null($this->modified)) {
            try {
                $this->modified = $this->getProvidedCHO()->getLiteral("<http://purl.org/dc/terms/modified>");
                if(is_null($this->modified)) {
                    $this->modified = $this->getIssued();
                }
            } catch(\Exception $e) {
                $this->modified = null;
            }
        }
        return $this->modified;
    }

    public function getModifiedValue() {
        $modified = $this->getModified();
        return is_null($modified)?null:$modified->getValue();
    }

    public function setModified($value) {
        $modified = $this->getModified();
        if($value && (!$modified || $modified->getValue() != $value) ) {

            $newModified = new Literal($value, "http://purl.org/dc/terms/W3CDTF");
            $this->setSimpleProperty($this->getProvidedCHO(), 'http://purl.org/dc/terms/modified', $modified, $newModified);

            $this->modified = null;
        }
    }

    public function getMediaArray() {

        if(is_null($this->mediaArray)) {
            //TODO: add media type
            $this->mediaArray = [];

            $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) {
                $extent = $webResource->getLiteral("<http://purl.org/dc/terms/extent>");
                $extent = is_null($extent)?null:$extent->getValue();
                $extent_ms = Utils::iso8601IntervalToMillis($extent);
                $format = $webResource->getLiteral("dc11:format");

                $this->mediaArray[$webResource->getUri()] = [
                    'url' => $webResource->getUri(),
                    'format' => is_null($format)?null:$format->getValue(),
                    'extent' => $extent,
                    'extent_ms' => $extent_ms,
                    'master' => (($webResource->getUri() === $masterUrl)?true:false)
                ];
            }
        }
        return $this->mediaArray;
    }

    public function getTypes() {
        return $this->getProvidedCHO()->all('dc11:type');
    }

    public function getDiscourseTypes() {
        return array_values(array_filter($this->getTypes(), function($v) {
            return $v instanceof Literal && $v->getDatatypeUri() === Config::get('corpusparole.olac_discourse_type')['uri'];
        }));
    }

    public function getOtherTypes() {
        $res = array_values(array_filter($this->getTypes(), function($v) {
            return $v instanceof Resource || $v->getDatatypeUri() !== Config::get('corpusparole.olac_discourse_type')['uri'];
        }));
        return $res;
    }

    public function getContributors() {
        if(is_null($this->contributors)) {
            $this->contributors = array_reduce(
                CocoonUtils::OLAC_ROLES,
                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 (is_null($contribDef['url'])) {
                if(is_null($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 (is_null($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) {
            $literalValue = new Literal($discourseType, null, Config::get('corpusparole.olac_discourse_type')['uri']);
            $this->getProvidedCHO()->delete('dc11:type', $literalValue);
            $this->currentDelta->getDeletedGraph()->add($this->getProvidedCHO(), 'dc11:type', new Literal($discourseType, null, Config::get('corpusparole.olac_discourse_type')['uri']));
        }

        // and re-add them
        foreach($discoursesTypes as $dType) {
            $this->getProvidedCHO()->add('dc11:type', new Literal($dType, null, Config::get('corpusparole.olac_discourse_type')['uri']));
            $this->currentDelta->getAddedGraph()->add($this->getProvidedCHO(), 'dc11:type', new Literal($dType, null, Config::get('corpusparole.olac_discourse_type')['uri']));
        }

        $this->clearMemoizationCache();
    }

    public function isIsomorphic($doc) {
        return Isomorphic::isomorphic($this->graph, $doc->graph);
    }

    /*
     * Clone document.
     * clone also the innerDocumenent
     */
    public function __clone() {

        $this->graph = new Graph($this->graph->getUri(), $this->graph->toRdfPhp());
    }

    public function jsonSerialize() {
        if(!$this->graph) {
            return [
                'id' => $this->getId(),
            ];
        } else {
            $mediaArray = array_map(
                function($m) {
                    $f = Utils::processLiteralOrString($m['format']);
                    $res = $m;
                    $res['format'] = $f;
                    return $res;},
                $this->getMediaArray()
            );

            $publishers = array_map(
                function($v) { return Utils::processLiteralOrString($v); },
                $this->getPublishers()
            );

            $contributors = array_map(
                function($c) { unset($c['nameLiteral']); return $c; },
                $this->getContributors()
            );

            return [
                'id' => $this->getId(),
                'uri' => $this->getUri(),
                'title' => $this->getTitleValue(),
                'language' => $this->getLanguageValue(),
                'modified' => $this->getModifiedValue(),
                'publishers' => $publishers,
                'contributors' => $contributors,
                'mediaArray'=> $mediaArray
            ];
        }
    }

}