server/src/app/Repositories/RdfDocumentRepository.php
author nowmad@23.1.168.192.in-addr.arpa
Fri, 13 Nov 2015 11:01:27 +0100
changeset 13 ba32dd4cf8d3
parent 4 f55970e41793
child 19 eadaf0b8f02e
permissions -rw-r--r--
update styles

<?php

namespace CorpusParole\Repositories;

use Config;
use Log;
use CorpusParole\Models\Document;
use CorpusParole\Libraries\CorpusParoleException;
use CorpusParole\Libraries\Sparql\SparqlClient;

use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;

/**
 * Implement the DocumentRepository using EasyRdf
 * TODO: cetainly split the transaction management (+add, +delete +transaction ) to an extarnal class -> for this extend the sparql client.
 */
class RdfDocumentRepository implements DocumentRepository {

    private $sparqlClient;

    public function __construct(SparqlClient $sparqlClient) {
        $this->sparqlClient = $sparqlClient;
    }

    public function getSparqlClient() {
        return $this->sparqlClient;
    }

    private function queryDocs($query) {
        $docs = $this->sparqlClient->query($query);

        $data = [];

        foreach ($docs as $doc) {
            array_push($data, new Document($doc->uri->getUri()));
        }

        return $data;
    }

    public function all() {

        return $this->queryDocs("SELECT DISTINCT ?uri WHERE { GRAPH ?uri { ?s ?p ?o } } ORDER BY ?uri");

    }

    public function get($id) {

        $docUri = Config::get('corpusparole.cocoon_doc_id_base_uri').$id;

        // We want the CBD (Concise Bounded Description, cf. http://www.w3.org/Submission/CBD/)
        // WARNING: This seems to work in sesame for our dataset.
        $doc = $this->sparqlClient->query(
            "CONSTRUCT { ?s ?p ?o } WHERE { GRAPH <$docUri> { ?s ?p ?o } }"
        );
        //TODO: return null if not found
        if($doc->isEmpty()) {
            return null;
        }

        return new Document($docUri, $doc);

    }

    /**
     * save document.
     * @return boolean true if a transaction was started, false otherwise
     * @throws CorpusParoleException if one of the operation could not be performed
     */
    public function save(Document $doc) {

        $transactionStarted = $this->sparqlClient->startTransaction();

        try {
            foreach($doc->getDeltaList() as $delta) {
                $this->sparqlClient->delete($delta->getDeletedGraph());
                $this->sparqlClient->add($delta->getAddedGraph());
            }
            if($transactionStarted) {
                $transactionStarted = false;
                return $this->sparqlClient->commit();
            }
            else  {
                return false;
            }
        }
        catch(CorpusParoleException $e) {
            if($transactionStarted) {
                $this->sparqlClient->rollback();
            }
            throw $e;
        }
    }

    public function getCount() {
        $res = $this->sparqlClient->query("SELECT (COUNT (DISTINCT ?g) as ?count) WHERE { GRAPH ?g { ?s ?p ?o } }");
        assert(!is_null($res) && $res->count()==1);
        return $res[0]->count->getValue();
    }

    //SELECT ?g WHERE { GRAPH ?g { ?s ?p ?o } }

    /**
     * Paginate all document as a paginator.
     *
     * @param  int  $perPage
     * @param  string  $pageName
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function paginateAll($perPage = 15, $pageName = 'page')
    {
        $page = Paginator::resolveCurrentPage($pageName);

        $total = $this->getCount();

        $offset = max(0,($page - 1) * $perPage);

        $query = "SELECT DISTINCT ?uri WHERE { GRAPH ?uri { ?s ?p ?o } } ORDER BY ?uri OFFSET $offset LIMIT $perPage";

        $results = $this->queryDocs($query);

        return new LengthAwarePaginator($results, $total, $perPage, $page, [
            'path' => Paginator::resolveCurrentPath(),
            'pageName' => $pageName,
        ]);
    }


}