50 public function __construct(SparqlClient $sparqlClient, Client $httpClient) { |
53 public function __construct(SparqlClient $sparqlClient, Client $httpClient) { |
51 $this->sparqlClient = $sparqlClient; |
54 $this->sparqlClient = $sparqlClient; |
52 $this->httpClient = $httpClient; |
55 $this->httpClient = $httpClient; |
53 } |
56 } |
54 |
57 |
|
58 public function getSparqlClient($timeout = null) { |
|
59 if(is_null($timeout)) { |
|
60 $timeout = config('corpusparole.sparql_client_timeout'); |
|
61 } |
|
62 $queryUrl = config('corpusparole.sesame_query_url'); |
|
63 if($timeout > 0) { |
|
64 $queryUrl = $queryUrl . |
|
65 ((strlen(parse_url($queryUrl, PHP_URL_QUERY)) > 0)?"&":"?"). |
|
66 "timeout=$timeout"; |
|
67 } |
|
68 return new \EasyRdf\Sparql\Client($queryUrl, config('corpusparole.sesame_update_url')); |
|
69 } |
|
70 |
55 // display form |
71 // display form |
56 public function index() { |
72 public function index() { |
57 return view('sparql/sparqlClientForm'); |
73 return view('sparql/sparqlClientForm'); |
58 } |
74 } |
59 |
75 |
60 private function querySelect(Request $request, $query, $analyser) { |
76 private function readDocs($docs, $fields) { |
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 = []; |
77 $results = []; |
67 foreach($docs as $row) { |
78 foreach($docs as $row) { |
68 $results[] = array_reduce($fields, function($res, $field) use ($row) { |
79 $results[] = array_reduce($fields, function($res, $field) use ($row) { |
69 if(isset($row->$field)) { |
80 if(isset($row->$field)) { |
70 $res[$field] = RdfHelper::serialiseValue($row->$field); |
81 $res[$field] = RdfHelper::serialiseValue($row->$field); |
72 $res[$field] = "<span class=\"corpus-rdf-blank-value\"> </span>"; |
83 $res[$field] = "<span class=\"corpus-rdf-blank-value\"> </span>"; |
73 } |
84 } |
74 return $res; |
85 return $res; |
75 }, []); |
86 }, []); |
76 } |
87 } |
|
88 return $results; |
|
89 } |
|
90 |
|
91 private function abort($code, $message, $exception) { |
|
92 throw new \Symfony\Component\HttpKernel\Exception\HttpException($code, $message, $exception, []); |
|
93 } |
|
94 |
|
95 private function processQueryException($exception) { |
|
96 $message = $exception->getMessage(); |
|
97 if($exception instanceof \EasyRdf\Http\Exception) { |
|
98 if(preg_match("/SPARQL\squery/", $message)) { |
|
99 $this->abort(400, "La requête SPARQL n'est pas reconnue", $exception); |
|
100 } else { |
|
101 $this->abort(500, "Problème HTTP lors de la requête SPARQL", $exception); |
|
102 } |
|
103 } elseif($exception instanceof \EasyRdf\Exception) { |
|
104 if(preg_match("/timed\sout/i", $message)) { |
|
105 $this->abort(408, "Time-out causé par la requête SPARQL", $exception); |
|
106 } else { |
|
107 $this->abort(500, "Problème dans la requête SPARQL", $exception); |
|
108 } |
|
109 } else { |
|
110 $this->abort(500, "Erreur serveur lors de la requête", $exception); |
|
111 } |
|
112 } |
|
113 |
|
114 private function querySelect(Request $request, $query, $analyser) { |
|
115 |
|
116 $limit = intval($request->input('limit', config('corpusparole.sparql_client_default_limit'))); |
|
117 |
|
118 if($limit === 0 || !is_null($analyser->getLimit()) || !is_null($analyser->getOffset()) ) { |
|
119 try { |
|
120 $docs = $this->getSparqlClient()->query($query); |
|
121 } catch(\Exception $exception) { |
|
122 $this->processQueryException($exception); |
|
123 } |
|
124 |
|
125 $fields = $docs->getFields(); |
|
126 $results = $this->readDocs($docs, $fields); |
|
127 $count = count($results); |
|
128 |
|
129 } else { |
|
130 |
|
131 $page = Paginator::resolveCurrentPage(config('corpusparole.pagination_page_param')); |
|
132 assert(is_null($page) || is_numeric($page)); |
|
133 |
|
134 $offset = max(0,($page - 1) * $limit); |
|
135 |
|
136 try { |
|
137 $countResult = $this->getSparqlClient()->query($analyser->getCountQuery()); |
|
138 $docs = $this->getSparqlClient()->query($query . " LIMIT $limit OFFSET $offset"); |
|
139 } catch(\Exception $exception) { |
|
140 $this->processQueryException($exception); |
|
141 } |
|
142 |
|
143 |
|
144 $countField = $countResult->getFields()[0]; |
|
145 $count = $countResult->current()->$countField->getValue(); |
|
146 |
|
147 $fields = $docs->getFields(); |
|
148 |
|
149 $results = new LengthAwarePaginator($this->readDocs($docs, $fields), $count, $limit, $page, [ |
|
150 'path' => Paginator::resolveCurrentPath(), |
|
151 'pageName' => config('corpusparole.pagination_page_param'), |
|
152 ]); |
|
153 } |
|
154 |
77 $namespaces = array_reduce(array_keys(RdfHelper::getPrefixes()), function($res, $p) { |
155 $namespaces = array_reduce(array_keys(RdfHelper::getPrefixes()), function($res, $p) { |
78 $res[$p] = RdfNamespace::namespaces()[$p]; |
156 $res[$p] = RdfNamespace::namespaces()[$p]; |
79 return $res; |
157 return $res; |
80 }, []); |
158 }, []); |
|
159 |
81 $data = [ |
160 $data = [ |
82 'query' => $query, |
161 'query' => $query, |
83 'count' => $count, |
162 'count' => $count, |
84 'fields' => $fields, |
163 'fields' => $fields, |
85 'fieldPrefix' => "?", |
164 'fieldPrefix' => "?", |
90 $view = 'sparql/sparqlClientResultList'; |
169 $view = 'sparql/sparqlClientResultList'; |
91 return [$view, $data]; |
170 return [$view, $data]; |
92 } |
171 } |
93 |
172 |
94 private function queryGraph(Request $request, $query, $analyser) { |
173 private function queryGraph(Request $request, $query, $analyser) { |
95 |
174 try { |
96 $docs = $this->sparqlClient->query($query); |
175 $docs = $this->getSparqlClient()->query($query); |
|
176 } catch(\Exception $exception) { |
|
177 $this->processQueryException($exception); |
|
178 } |
|
179 |
|
180 |
97 $fields = ["subject", "predicate", "object"]; |
181 $fields = ["subject", "predicate", "object"]; |
98 $results = []; |
182 $results = []; |
99 foreach ($docs->resources() as $resource ) { |
183 foreach ($docs->resources() as $resource ) { |
100 foreach ($resource->propertyUris() as $property) { |
184 foreach ($resource->propertyUris() as $property) { |
101 $propertyResource = $docs->resource($property); |
185 $propertyResource = $docs->resource($property); |
127 |
211 |
128 return [$view, $data]; |
212 return [$view, $data]; |
129 } |
213 } |
130 |
214 |
131 private function queryAsk(Request $request, $query, $analyser) { |
215 private function queryAsk(Request $request, $query, $analyser) { |
|
216 try { |
|
217 $result = $this->getSparqlClient()->query($query); |
|
218 } catch(\Exception $exception) { |
|
219 $this->processQueryException($exception); |
|
220 } |
|
221 |
132 $data = [ |
222 $data = [ |
133 'results' => $this->sparqlClient->query($query), |
223 'results' => $result, |
134 'namespaces' => $analyser->getPrefixes() |
224 'namespaces' => $analyser->getPrefixes() |
135 ]; |
225 ]; |
136 |
226 |
137 $view = 'sparql/sparqlClientResultBoolean'; |
227 $view = 'sparql/sparqlClientResultBoolean'; |
138 return [$view, $data]; |
228 return [$view, $data]; |
157 } elseif($queryType === SparqlQueryAnalyser::GRAPH_QUERY) { |
247 } elseif($queryType === SparqlQueryAnalyser::GRAPH_QUERY) { |
158 list($view, $data) = $this->queryGraph($request, $query, $analyser); |
248 list($view, $data) = $this->queryGraph($request, $query, $analyser); |
159 } elseif($queryType === SparqlQueryAnalyser::ASK_QUERY) { |
249 } elseif($queryType === SparqlQueryAnalyser::ASK_QUERY) { |
160 list($view, $data) = $this->queryAsk($request, $query, $analyser); |
250 list($view, $data) = $this->queryAsk($request, $query, $analyser); |
161 } else { |
251 } else { |
162 //return 500 |
252 abort(400, "La requête n'est pas reconnue"); |
163 abort(500, "Serialization format unknown"); |
|
164 } |
253 } |
165 |
254 |
166 return view($view, $data); |
255 return view($view, $data); |
167 |
256 |
168 } |
257 } |
180 |
269 |
181 if(!empty($format)){ |
270 if(!empty($format)){ |
182 $headers['Accept'] = $format; |
271 $headers['Accept'] = $format; |
183 } |
272 } |
184 |
273 |
185 $sesameResp = $this->httpClient->get(config('corpusparole.sesame_query_url'), ['query' => $request->all(), 'headers' => $headers]); |
274 $queryParams = $request->all(); |
|
275 $queryParams['timeout'] = config('corpusparole.sparql_client_timeout'); |
|
276 $queryUrl = config('corpusparole.sesame_query_url'); |
|
277 |
|
278 try { |
|
279 $sesameResp = $this->httpClient->post($queryUrl, ['form_params' => $queryParams, 'headers' => $headers]); |
|
280 } catch(\GuzzleHttp\Exception\ServerException $exception) { |
|
281 if($exception->getCode() == 503) { |
|
282 $this->abort(408, "Time-out causé par la requête SPARQL", $exception); |
|
283 } else { |
|
284 $this->abort(500, "Problème lors de la requête SPARQL", $exception); |
|
285 } |
|
286 |
|
287 } catch(\GuzzleHttp\Exception\RequestException $exception) { |
|
288 $message = $exception->getMessage(); |
|
289 if(preg_match("/MALFORMED\sQUERY/i", $message)) { |
|
290 $abortMessage = "Requête SPARQL mal-formée"; |
|
291 } else { |
|
292 $abortMessage = "Problème lors de la requête SPARQL"; |
|
293 } |
|
294 $this->abort($exception->getCode(), $abortMessage, $exception); |
|
295 } catch(\Exception $exception) { |
|
296 $this->abort(500, "Erreur serveur lors de la requête", $exception); |
|
297 } |
186 |
298 |
187 $resp = response((string)$sesameResp->getBody(), $sesameResp->getStatusCode()); |
299 $resp = response((string)$sesameResp->getBody(), $sesameResp->getStatusCode()); |
188 foreach ($sesameResp->getHeaders() as $name => $values) { |
300 foreach ($sesameResp->getHeaders() as $name => $values) { |
189 if($name != 'Transfer-Encoding') { |
301 if($name != 'Transfer-Encoding') { |
190 $resp->header($name, $values); |
302 $resp->header($name, $values); |