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 ) { |
|
|
|
|
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
|
|
|
|
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.