Smalyshev has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/404064 )
Change subject: Add SPARQL client to core
......................................................................
Add SPARQL client to core
This will be used for deep category search implementation,
also Wikibase one in repo/maintenance will be changed
to use the same codebase.
Bug: T184840
Change-Id: Ie8dd4a5aff55d90f02426f1430ed5214c7327bbc
---
A includes/sparql/SPARQLClient.php
A includes/sparql/SPARQLException.php
2 files changed, 170 insertions(+), 0 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core
refs/changes/64/404064/1
diff --git a/includes/sparql/SPARQLClient.php b/includes/sparql/SPARQLClient.php
new file mode 100644
index 0000000..e8ca478
--- /dev/null
+++ b/includes/sparql/SPARQLClient.php
@@ -0,0 +1,157 @@
+<?php
+
+namespace SPARQL;
+
+use MWHttpRequest;
+
+/**
+ * Simple SPARQL client
+ *
+ * @license GPL-2.0+
+ * @author Stas Malyshev
+ */
+class SPARQLClient {
+
+ /**
+ * Limit on how long can be the query to be sent by GET.
+ */
+ const MAX_GET_SIZE = 2048;
+
+ /**
+ * User agent for HTTP requests.
+ * @var string
+ */
+ const SPARQL_USER_AGENT = "Mediawiki SPARQL Client";
+
+ /**
+ * Query timeout (seconds)
+ * @var int
+ */
+ private $timeout = 30;
+
+ /**
+ * SPARQL endpoint URL
+ * @var string
+ */
+ private $endpoint;
+
+ /**
+ * Client options
+ * @var array
+ */
+ private $options = [];
+
+ /**
+ * @param string $url SPARQL Endpoint
+ */
+ public function __construct( $url ) {
+ $this->endpoint = $url;
+ }
+
+ /**
+ * Set query timeout (in seconds)
+ * @param int $timeout
+ * @return $this
+ */
+ public function setTimeout( $timeout ) {
+ if ( $timeout >= 0 ) {
+ $this->timeout = $timeout;
+ }
+ return $this;
+ }
+
+ /**
+ * Set client options
+ * @param array $options
+ * @return $this
+ */
+ public function setClientOptions( $options ) {
+ $this->options = $options;
+ return $this;
+ }
+
+ /**
+ * Query SPARQL endpoint
+ *
+ * @param string $sparql query
+ * @param bool $rawData Whether to return only values or full data
objects
+ *
+ * @return array List of results, one row per array element
+ * Each row will contain fields indexed by variable name.
+ * @throws SPARQLException
+ */
+ public function query( $sparql, $rawData = false ) {
+ $queryData = [ "query" => $sparql, "format" => "json" ];
+ $options = array_merge( [ 'method' => 'GET' ], $this->options );
+
+ if ( empty( $options['userAgent'] ) ) {
+ $options['userAgent'] = self::SPARQL_USER_AGENT;
+ }
+
+ if ( $this->timeout >= 0 ) {
+ // Blazegraph setting, see
https://wiki.blazegraph.com/wiki/index.php/REST_API
+ $queryData['maxQueryTimeMillis'] = $this->timeout *
1000;
+ $options['timeout'] = $this->timeout;
+ }
+
+ if ( strlen($sparql) > self::MAX_GET_SIZE ) {
+ // big requests go to POST
+ $options['method'] = 'POST';
+ $options['postData'] = 'query=' . urlencode( $sparql );
+ unset( $queryData['query'] );
+ }
+
+ $url = $this->endpoint . '?' . http_build_query( $queryData );
+ $request = MWHttpRequest::factory( $url, $options );
+
+ $status = $request->execute();
+
+ if ( !$status->isOK() ) {
+ throw new SPARQLException( "HTTP error:
{$status->getWikiText()}" );
+ }
+ $result = $request->getContent();
+ \MediaWiki\suppressWarnings();
+ $data = json_decode( $result, true );
+ \MediaWiki\restoreWarnings();
+ if ( !$data ) {
+ throw new SPARQLException( "HTTP request failed,
response:\n" .
+ substr( $result, 1024 ) );
+ }
+
+ return $this->extractData( $data, $rawData );
+ }
+
+ /**
+ * Extract data from SPARQL response format.
+ * The response must be in format described in:
+ * https://www.w3.org/TR/sparql11-results-json/
+ *
+ * @param array $data SPARQL result
+ * @param bool $rawData Whether to return only values or full data
objects
+ *
+ * @return array List of results, one row per element.
+ */
+ private function extractData( $data, $rawData = false ) {
+ $result = [];
+ if ( $data && !empty( $data['results'] ) ) {
+ $vars = $data['head']['vars'];
+ $resrow = [];
+ foreach ( $data['results']['bindings'] as $row ) {
+ foreach ( $vars as $var ) {
+ if ( !isset( $row[$var] ) ) {
+ $resrow[$var] = null;
+ continue;
+ }
+ if ( $rawData ) {
+ $resrow[$var] = $row[$var];
+ } else {
+ $resrow[$var] =
$row[$var]['value'];
+ }
+ }
+ $result[] = $resrow;
+ }
+ }
+ return $result;
+ }
+
+}
diff --git a/includes/sparql/SPARQLException.php
b/includes/sparql/SPARQLException.php
new file mode 100644
index 0000000..1586b19
--- /dev/null
+++ b/includes/sparql/SPARQLException.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace SPARQL;
+
+use Exception;
+
+/**
+ * Exception for SPARQLClient
+ * @license GPL-2.0+
+ * @author Stas Malyshev
+ */
+class SPARQLException extends Exception {
+}
--
To view, visit https://gerrit.wikimedia.org/r/404064
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie8dd4a5aff55d90f02426f1430ed5214c7327bbc
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Smalyshev <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits