server/src/app/Http/Controllers/Sparql/SparqlClientController.php
changeset 386 c731ab9b934d
child 387 7fba86fa8604
equal deleted inserted replaced
385:f8200c5482ec 386:c731ab9b934d
       
     1 <?php
       
     2 
       
     3 namespace CorpusParole\Http\Controllers\Sparql;
       
     4 
       
     5 use Log;
       
     6 
       
     7 use Illuminate\Http\Request;
       
     8 use GuzzleHttp\Client;
       
     9 use EasyRdf\Sparql\Result as SparqlResult;
       
    10 use EasyRdf\Graph;
       
    11 use EasyRdf\RdfNamespace;
       
    12 
       
    13 use CorpusParole\Http\Controllers\Controller;
       
    14 use CorpusParole\Libraries\Utils;
       
    15 
       
    16 use CorpusParole\Libraries\Sparql\SparqlClient;
       
    17 use CorpusParole\Libraries\Sparql\SparqlQueryAnalyser;
       
    18 use RdfHelper;
       
    19 
       
    20 class SparqlClientController extends Controller
       
    21 {
       
    22 
       
    23     const HEADERS_FORWARDED = [ "host", "user-agent", "accept", "accept-language", "accept-encoding", "connection" ];
       
    24 
       
    25     const SELECT_RESULT_FORMAT = [
       
    26         "SPARQL/CSV" => "text/csv",
       
    27         "SPARQL/JSON" => "application/sparql-results+json",
       
    28         "SPARQL/XML" => "application/sparql-results+xml",
       
    29         "SPARQL/TSV" => "text/tab-separated-values",
       
    30         "BINARY" => "application/x-binary-rdf-results-table"
       
    31     ];
       
    32 
       
    33     const GRAPH_RESULT_FORMAT = [
       
    34         "N-Triples" => "application/n-triples",
       
    35         "RDF/XML" => "application/rdf+xml",
       
    36         "Turtle" => "text/turtle",
       
    37         "N3" => "text/n3",
       
    38         "RDF/JSON" => "application/rdf+json",
       
    39         "TriG" => "application/trig",
       
    40         "N-Quads" => "application/n-quads",
       
    41         "BinaryRDF" => "application/x-binary-rdf",
       
    42         "TriX" => "application/trix",
       
    43         "JSON-LD" => "application/ld+json"
       
    44     ];
       
    45 
       
    46 
       
    47     private $sparqlClient;
       
    48     private $httpClient;
       
    49 
       
    50     public function __construct(SparqlClient $sparqlClient, Client $httpClient) {
       
    51         $this->sparqlClient = $sparqlClient;
       
    52         $this->httpClient = $httpClient;
       
    53     }
       
    54 
       
    55     // display form
       
    56     public function index() {
       
    57         return view('sparql/sparqlClientForm');
       
    58     }
       
    59 
       
    60     private function querySelect(Request $request, $query, $analyser) {
       
    61         $countResult = $this->sparqlClient->query($analyser->getCountQuery());
       
    62         $countField = $countResult->getFields()[0];
       
    63         $count = $countResult->current()->$countField;
       
    64         $docs = $this->sparqlClient->query($query);
       
    65         $fields = $docs->getFields();
       
    66         $results = [];
       
    67         foreach($docs as $row) {
       
    68             $results[] = array_reduce($fields, function($res, $field) use ($row) {
       
    69                 if(isset($row->$field)) {
       
    70                     $res[$field] = RdfHelper::serialiseValue($row->$field);
       
    71                 } else {
       
    72                     $res[$field] = "<span class=\"corpus-rdf-blank-value\">&nbsp;</span>";
       
    73                 }
       
    74                 return $res;
       
    75             }, []);
       
    76         }
       
    77         $namespaces = array_reduce(array_keys(RdfHelper::getPrefixes()), function($res, $p) {
       
    78             $res[$p] = RdfNamespace::namespaces()[$p];
       
    79             return $res;
       
    80         }, []);
       
    81         $data = [
       
    82             'query' => $query,
       
    83             'count' => $count,
       
    84             'fields' => $fields,
       
    85             'fieldPrefix' => "?",
       
    86             'results' => $results,
       
    87             'namespaces' => $namespaces,
       
    88             'downloadFormats' => self::SELECT_RESULT_FORMAT
       
    89         ];
       
    90         $view = 'sparql/sparqlClientResultList';
       
    91         return [$view, $data];
       
    92     }
       
    93 
       
    94     private function queryGraph(Request $request, $query, $analyser) {
       
    95 
       
    96         $docs = $this->sparqlClient->query($query);
       
    97         $fields = ["subject", "predicate", "object"];
       
    98         $results = [];
       
    99         foreach ($docs->resources() as $resource ) {
       
   100             foreach ($resource->propertyUris() as $property) {
       
   101                 $propertyResource = $docs->resource($property);
       
   102                 foreach ($resource->all($propertyResource) as $value) {
       
   103                     $results[] = [
       
   104                         'subject' => RdfHelper::serialiseValue($resource),
       
   105                         'predicate'=> RdfHelper::serialiseValue($propertyResource),
       
   106                         'object'=> RdfHelper::serialiseValue($value)
       
   107                     ];
       
   108                 }
       
   109             }
       
   110         }
       
   111         $namespaces = array_reduce(array_keys(RdfHelper::getPrefixes()), function($res, $p) {
       
   112             $res[$p] = RdfNamespace::namespaces()[$p];
       
   113             return $res;
       
   114         }, []);
       
   115 
       
   116 
       
   117         $data = [
       
   118             'query' => $query,
       
   119             'count' => count($results),
       
   120             'fields' => $fields,
       
   121             'fieldPrefix' => "",
       
   122             'results' => $results,
       
   123             'namespaces' => $namespaces,
       
   124             'downloadFormats' => self::GRAPH_RESULT_FORMAT
       
   125         ];
       
   126         $view = 'sparql/sparqlClientResultList';
       
   127 
       
   128         return [$view, $data];
       
   129     }
       
   130 
       
   131     private function queryAsk(Request $request, $query, $analyser) {
       
   132         $data = [
       
   133             'results' => $this->sparqlClient->query($query),
       
   134             'namespaces' => $analyser->getPrefixes()
       
   135         ];
       
   136 
       
   137         $view = 'sparql/sparqlClientResultBoolean';
       
   138         return [$view, $data];
       
   139     }
       
   140 
       
   141     private function showHtml(Request $request) {
       
   142 
       
   143         $query = $request->input('query');
       
   144 
       
   145         $analyser = new SparqlQueryAnalyser($query);
       
   146 
       
   147         $queryType = $analyser->getQueryType();
       
   148 
       
   149         $namespaces = $analyser->getPrefixes();
       
   150 
       
   151         foreach($namespaces as $prefix => $nUri) {
       
   152             RdfNamespace::set($prefix,$nUri);
       
   153         }
       
   154 
       
   155         if($queryType === SparqlQueryAnalyser::SELECT_QUERY) {
       
   156             list($view, $data) = $this->querySelect($request, $query, $analyser);
       
   157         } elseif($queryType === SparqlQueryAnalyser::GRAPH_QUERY) {
       
   158             list($view, $data) = $this->queryGraph($request, $query, $analyser);
       
   159         } elseif($queryType === SparqlQueryAnalyser::ASK_QUERY) {
       
   160             list($view, $data) = $this->queryAsk($request, $query, $analyser);
       
   161         } else {
       
   162             //return 500
       
   163             abort(500, "Serialization format unknown");
       
   164         }
       
   165 
       
   166         return view($view, $data);
       
   167 
       
   168     }
       
   169 
       
   170 
       
   171     private function proxyQuery(Request $request, $format=null) {
       
   172         $query = $request->input('query');
       
   173         $headers = [];
       
   174         foreach (self::HEADERS_FORWARDED as $h) {
       
   175             $headerValue = $request->header($h);
       
   176             if($headerValue) {
       
   177                 $headers[$h] = $headerValue;
       
   178             }
       
   179         }
       
   180 
       
   181         if(!empty($format)){
       
   182             $headers['Accept'] = $format;
       
   183         }
       
   184 
       
   185         $sesameResp = $this->httpClient->get(config('corpusparole.sesame_query_url'), ['query' => $request->all(), 'headers' => $headers]);
       
   186 
       
   187         $resp = response((string)$sesameResp->getBody(), $sesameResp->getStatusCode());
       
   188         foreach ($sesameResp->getHeaders() as $name => $values) {
       
   189             if($name != 'Transfer-Encoding') {
       
   190                 $resp->header($name, $values);
       
   191             }
       
   192         }
       
   193 
       
   194         return $resp;
       
   195     }
       
   196 
       
   197     // display result
       
   198     public function show(Request $request) {
       
   199 
       
   200         $format = $request->input('format');
       
   201 
       
   202         if($format === 'text/html') {
       
   203             return $this->showHtml($request);
       
   204         } else {
       
   205             return $this->proxyQuery($request, $format);
       
   206         }
       
   207 
       
   208     }
       
   209 
       
   210     // do the query
       
   211     public function query(Request $request) {
       
   212         return $this->proxyQuery($request);
       
   213     }
       
   214 
       
   215 }