server/src/app/Models/Document.php
author ymh <ymh.work@gmail.com>
Sun, 05 Jun 2016 00:28:45 +0200
changeset 169 8fddc113095e
parent 168 17f10b56c079
child 260 64caee7ce38d
permissions -rw-r--r--
Correct proble on geo info merging + add geo resource

<?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 DocumentResult {

    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 $geoInfo = false;

    protected function clearMemoizationCache() {
        parent::clearMemoizationCache();
        $this->publishers = null;
        $this->mediaArray = null;
        $this->contributors = null;
        $this->subjects = null;
        $this->transcript = false;
        $this->geoInfo = false;
    }


    public function getPublishers() {
        if(is_null($this->publishers)) {
            try {
                $this->publishers = $this->getProvidedCHO()->all('dc11:publisher');
            } catch(\Exception $e) {
               $this->publishers = [];
            }
        }
        return $this->publishers;
    }

    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() {
        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 getTranscript() {
        if($this->transcript === false) {
            $this->parseWebResources();
        }
        return $this->transcript;
    }

    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 (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) {
            $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();
    }

    /**
     * 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;
    }

    /**
     *
     */
    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);
            }
        }
        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 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 = array_map(
                function($v) { return Utils::processLiteralResourceOrString($v); },
                $this->getPublishers()
            );

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

            $subjects = array_map(
                function($s) { return Utils::processLiteralResourceOrString($s); },
                $this->getSubjects()
            );

            $res = array_merge($res, [
                'publishers' => $publishers,
                'contributors' => $contributors,
                'subjects' => $subjects,
                'transcript' => $transcript,
                'mediaArray'=> $mediaArray,
                'geoInfo' => $geoInfo
            ]);

        }
        return $res;

    }

}