Completed
Pull Request — master (#36)
by
unknown
20:47
created

QueryResultFetcher::doMakeHttpRequestFor()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 0
cts 0
cp 0
rs 9.456
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
namespace SEQL\ByHttpRequest;
4
5
use Onoi\HttpRequest\HttpRequestFactory;
6
use SEQL\QueryEncoder;
7
use SEQL\QueryResultFactory;
8
use SMWQuery as Query;
9
10
/**
11
 * @license GNU GPL v2+
12
 * @since 1.0
13
 *
14
 * @author mwjames
15
 */
16
class QueryResultFetcher {
17
18
	/**
19
	 * @var HttpRequestFactory
20
	 */
21
	private $httpRequestFactory;
22
23
	/**
24
	 * @var QueryResultFactory
25
	 */
26
	private $queryResultFactory;
27
28
	/**
29
	 * @var JsonResponseParser
30
	 */
31
	private $jsonResponseParser;
32
33
	/**
34
	 * @var string
35
	 */
36
	private $httpRequestEndpoint = '';
37
38
	/**
39
	 * @var string
40
	 */
41
	private $repositoryTargetUrl = '';
42
43
	/**
44
	 * @var string
45
	 */
46
	private $httpResponseCachePrefix;
47
48
	/**
49
	 * @var integer
50
	 */
51
	private $httpResponseCacheLifetime;
52
53
	/**
54
	 * @var array
55
	 */
56
	private $credentials;
57
58
	/**
59
	 * @var string
60 6
	 */
61 6
	private static $cookies;
62 6
63 6
	/**
64 6
	 * @since 1.0
65
	 *
66
	 * @param HttpRequestFactory $httpRequestFactory
67
	 * @param QueryResultFactory $queryResultFactory
68
	 * @param JsonResponseParser $jsonResponseParser
69
	 */
70
	public function __construct( HttpRequestFactory $httpRequestFactory, QueryResultFactory $queryResultFactory, JsonResponseParser $jsonResponseParser, $credentials ) {
71 2
		$this->httpRequestFactory = $httpRequestFactory;
72 2
		$this->queryResultFactory = $queryResultFactory;
73 2
		$this->jsonResponseParser = $jsonResponseParser;
74
		$this->credentials = $credentials;
75
	}
76
77
	/**
78
	 * @since 1.0
79
	 *
80 2
	 * @param string $httpRequestEndpoint
81 2
	 */
82 2
	public function setHttpRequestEndpoint( $httpRequestEndpoint ) {
83
		$this->httpRequestEndpoint = $httpRequestEndpoint;
84
	}
85
86
	/**
87
	 * @since 1.0
88
	 *
89 1
	 * @param string $repositoryTargetUrl
90 1
	 */
91 1
	public function setRepositoryTargetUrl( $repositoryTargetUrl ) {
92
		$this->repositoryTargetUrl = $repositoryTargetUrl;
93
	}
94
95
	/**
96
	 * @since 1.0
97
	 *
98 1
	 * @param string $httpResponseCachePrefix
99 1
	 */
100 1
	public function setHttpResponseCachePrefix( $httpResponseCachePrefix ) {
101
		$this->httpResponseCachePrefix = $httpResponseCachePrefix;
102
	}
103
104
	/**
105
	 * @since 1.0
106
	 *
107
	 * @param integer $httpResponseCacheLifetime
108
	 */
109 5
	public function setHttpResponseCacheLifetime( $httpResponseCacheLifetime ) {
110
		$this->httpResponseCacheLifetime = $httpResponseCacheLifetime;
111 5
	}
112
113 5
	/**
114
	 * Authenticates query against remote wiki using 'login' api and stores
115 5
	 * cookies to use on other requests
116 3
	 *
117
	 * @param array $credentials
118
	 */
119 2
	public function doAuthenticateRemoteWiki( $credentials ) {
120 1
121 1
		$cookiefile = 'seql_'.time();
122 1
123
		$httpRequest = $this->httpRequestFactory->newCurlRequest();
124 1
125
		$httpRequest->setOption( CURLOPT_FOLLOWLOCATION, true );
126
127
		$httpRequest->setOption( CURLOPT_RETURNTRANSFER, true );
128 1
		$httpRequest->setOption( CURLOPT_FAILONERROR, true );
129
		$httpRequest->setOption( CURLOPT_SSL_VERIFYPEER, false );
130
		$httpRequest->setOption( CURLOPT_COOKIESESSION, true );
131
		$httpRequest->setOption( CURLOPT_COOKIEJAR, $cookiefile );
132 1
		$httpRequest->setOption( CURLOPT_COOKIEFILE, $cookiefile );
133
134 1
		$httpRequest->setOption( CURLOPT_URL, $this->httpRequestEndpoint . '?action=query&format=json&meta=tokens&type=login' );
135 1
136 1
		$response = $httpRequest->execute();
137 1
		$result = json_decode( $response, true );
138
139 1
		if( isset( $result['query']['tokens']['logintoken'] ) ) {
140
141 1
			$token = $result['query']['tokens']['logintoken'];
142 1
143 1
			$httpRequest->setOption( CURLOPT_FOLLOWLOCATION, true );
144
			$httpRequest->setOption( CURLOPT_RETURNTRANSFER, true );
145 1
			$httpRequest->setOption( CURLOPT_FAILONERROR, true );
146
			$httpRequest->setOption( CURLOPT_SSL_VERIFYPEER, false );
147
			$httpRequest->setOption( CURLOPT_POST, true );
148 5
			$httpRequest->setOption( CURLOPT_URL, $this->httpRequestEndpoint );
149
			$httpRequest->setOption( CURLOPT_COOKIEJAR, $cookiefile );
150 5
			$httpRequest->setOption( CURLOPT_COOKIEFILE, $cookiefile );
151
152 5
			$httpRequest->setOption( CURLOPT_POSTFIELDS, http_build_query( array(
153
					'action' => 'login',
154 5
					'format' => 'json',
155 4
					'lgname' => $credentials['username'],
156
					'lgpassword' => $credentials['password'],
157
					'lgtoken' => $token
158 1
				))
159 1
			);
160
161 1
			$response = $httpRequest->execute();
162
			$result = json_decode( $response, true );
163
164 1
			if ( isset( $result['login']['lguserid'] ) ) {
165 5
				self::$cookies = $cookiefile;
166 5
			}
167
168 5
		}
169
170 5
	}
171
172 5
	/**
173 5
	 * @since 1.0
174
	 *
175 5
	 * @param Query $query
176
	 *
177 5
	 * @return QueryResult
178 5
	 */
179 5
	public function fetchQueryResult( Query $query ) {
180
181 5
		$this->doResetPrintRequestsToQuerySource( $query );
182
183 5
		if( $this->credentials && !self::$cookies ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->credentials of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
184 5
			$this->doAuthenticateRemoteWiki( $this->credentials );
185
		}
186 5
187
		list( $result, $isFromCache ) = $this->doMakeHttpRequestFor( $query );
188 5
189
		if ( $result === array() || $result === false || $result === null ) {
190 5
			return $this->queryResultFactory->newEmptyQueryResult( $query );
191
		}
192
193
		if ( isset( $result['error'] ) ) {
194
			$query->addErrors(
195
				isset( $result['error']['info'] ) ? array( implode( ', ', $result['error'] ) ) : $result['error']['query']
196
			);
197
198
			return $this->queryResultFactory->newEmptyQueryResult( $query );
199
		}
200
201
		// Add the source from where the result was retrieved
202
		if ( isset( $result['query']['meta']['source'] ) ) {
203
			$result['query']['meta']['source'] = $query->getQuerySource();
204
		}
205
206
		$this->jsonResponseParser->doParse( $result );
207
208
		$queryResult = $this->queryResultFactory->newByHttpRequestQueryResult(
209
			$query,
210
			$this->jsonResponseParser
211
		);
212
213
		$queryResult->setFromCache( $isFromCache );
214
215
		$queryResult->setRemoteTargetUrl(
216
			str_replace( '$1', '',  $this->repositoryTargetUrl )
217
		);
218
219
		return $queryResult;
220
	}
221
222
	private function doResetPrintRequestsToQuerySource( $query ) {
223
224
		$querySource = $query->getQuerySource();
225
226
		foreach ( $query->getExtraPrintouts() as $printRequest ) {
227
228
			if ( $printRequest->getData() === null ) {
229
				continue;
230
			}
231
232
			$property = $printRequest->getData()->getDataItem();
233
			$property->setInterwiki( $querySource );
234
235
			$printRequest->getData()->setDataItem( $property );
236
237
			// Reset label after dataItem was re-added
238
			$printRequest->setLabel( $printRequest->getLabel() );
239
		}
240
	}
241
242
	private function doMakeHttpRequestFor( $query ) {
243
244
		$httpRequest = $this->httpRequestFactory->newCachedCurlRequest();
245
246
		$httpRequest->setOption( ONOI_HTTP_REQUEST_RESPONSECACHE_TTL, $this->httpResponseCacheLifetime );
247
		$httpRequest->setOption( ONOI_HTTP_REQUEST_RESPONSECACHE_PREFIX, $this->httpResponseCachePrefix . ':seql:' );
248
249
		$httpRequest->setOption( CURLOPT_FOLLOWLOCATION, true );
250
251
		$httpRequest->setOption( CURLOPT_RETURNTRANSFER, true );
252
		$httpRequest->setOption( CURLOPT_FAILONERROR, true );
253
		$httpRequest->setOption( CURLOPT_SSL_VERIFYPEER, false );
254
255
		$httpRequest->setOption( CURLOPT_URL, $this->httpRequestEndpoint . '?action=ask&format=json&query=' . QueryEncoder::rawUrlEncode( $query ) );
256
257
		$httpRequest->setOption( CURLOPT_HTTPHEADER, array(
258
			'Accept: application/json',
259
			'Content-Type: application/json; charset=utf-8'
260
		) );
261
262
		if( self::$cookies ) {
263
			$httpRequest->setOption( CURLOPT_COOKIEJAR, self::$cookies );
264
			$httpRequest->setOption( CURLOPT_COOKIEFILE, self::$cookies );
265
		}
266
267
		$response = $httpRequest->execute();
268
269
		return array( json_decode( $response, true ), $httpRequest->isFromCache() );
270
	}
271
272
}
273