|
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\"> </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 } |