1 |
|
<?php |
2 |
|
/** |
3 |
|
* Transport.php |
4 |
|
* 08-Nov-2011 |
5 |
|
* |
6 |
|
* PHP Version 5 |
7 |
|
* |
8 |
|
* @category Services |
9 |
|
* @package Services_OpenStreetMap |
10 |
|
* @author Ken Guest <kguest@php.net> |
11 |
|
* @license BSD http://www.opensource.org/licenses/bsd-license.php |
12 |
|
* @version Release: @package_version@ |
13 |
|
* @link http://pear.php.net/package/Services_OpenStreetMap |
14 |
|
*/ |
15 |
1 |
require_once 'Services/OpenStreetMap/Transport.php'; |
16 |
|
|
17 |
1 |
require_once 'Log.php'; |
18 |
1 |
require_once 'Log/null.php'; |
19 |
1 |
require_once 'HTTP/Request2.php'; |
20 |
|
|
21 |
|
/** |
22 |
|
* Services_OpenStreetMap_Transport |
23 |
|
* |
24 |
|
* @category Services |
25 |
|
* @package Services_OpenStreetMap |
26 |
|
* @author Ken Guest <kguest@php.net> |
27 |
|
* @license BSD http://www.opensource.org/licenses/bsd-license.php |
28 |
|
* @link Transport.php |
29 |
|
*/ |
30 |
|
class Services_OpenStreetMap_Transport_HTTP |
31 |
1 |
implements Services_OpenStreetMap_Transport |
32 |
|
{ |
33 |
|
/** |
34 |
|
* __construct |
35 |
|
* |
36 |
|
* @return Services_OpenStreetMap_Transport_HTTP |
37 |
|
*/ |
38 |
|
public function __construct() |
39 |
|
{ |
40 |
102 |
$this->setConfig(new Services_OpenStreetMap_Config()); |
41 |
102 |
$this->setRequest(new HTTP_Request2()); |
42 |
102 |
$this->setLog(new Log_null(null, null)); |
43 |
|
} |
44 |
|
|
45 |
|
/** |
46 |
|
* The HTTP_Request2 instance. |
47 |
|
* |
48 |
|
* Customise this for proxy settings etc with the getRequest/setRequest |
49 |
|
* methods if necessary. |
50 |
|
* |
51 |
|
* @var HTTP_Request2 $request |
52 |
|
* @internal |
53 |
|
* @see Services_OpenStreetMap::getRequest |
54 |
|
* @see Services_OpenStreetMap::setRequest |
55 |
|
*/ |
56 |
|
protected $request = null; |
57 |
|
|
58 |
|
/** |
59 |
|
* @var Services_OpenStreetMap_Config $config |
60 |
|
*/ |
61 |
|
protected $config = null; |
62 |
|
|
63 |
|
/** |
64 |
|
* @var Log $log |
65 |
|
*/ |
66 |
|
protected $log = null; |
67 |
|
|
68 |
|
|
69 |
|
|
70 |
|
/** |
71 |
|
* Send request to OSM server and return the response. |
72 |
|
* |
73 |
|
* @param string $url URL |
74 |
|
* @param string $method GET (default)/POST/PUT |
75 |
|
* @param string $user user (optional for read-only actions) |
76 |
|
* @param string $password password (optional for read-only actions) |
77 |
|
* @param string $body body (optional) |
78 |
|
* @param array $post_data (optional) |
79 |
|
* @param array $headers (optional) |
80 |
|
* |
81 |
|
* @return HTTP_Request2_Response |
82 |
|
* @throws Services_OpenStreetMap_Exception If something unexpected has |
83 |
|
* happened while conversing with |
84 |
|
* the server. |
85 |
|
*/ |
86 |
|
public function getResponse( |
87 |
|
$url, |
88 |
|
$method = HTTP_Request2::METHOD_GET, |
89 |
|
$user = null, |
90 |
|
$password = null, |
91 |
|
$body = null, |
92 |
|
array $post_data = null, |
93 |
|
array $headers = null |
94 |
|
) { |
95 |
76 |
$response = null; |
96 |
76 |
$eMsg = null; |
97 |
|
|
98 |
76 |
if ($this->getConfig()->getValue('verbose')) { |
99 |
|
$this->log->debug($url); |
100 |
|
} |
101 |
|
|
102 |
76 |
$request = $this->getRequest(); |
103 |
76 |
$request->setUrl($url); |
104 |
76 |
$request->setMethod($method); |
105 |
76 |
$request->setAdapter($this->getConfig()->getValue('adapter')); |
106 |
|
|
107 |
|
|
108 |
76 |
$request->setHeader( |
109 |
76 |
'User-Agent', |
110 |
76 |
$this->getConfig()->getValue('User-Agent') |
111 |
76 |
); |
112 |
|
|
113 |
76 |
if ($user !== null && $password !== null) { |
114 |
11 |
$request->setAuth($user, $password); |
115 |
11 |
} |
116 |
76 |
if ($post_data != array()) { |
117 |
|
$request->setMethod(HTTP_Request2::METHOD_POST); |
118 |
|
foreach ($post_data as $key => $value) { |
119 |
|
$request->addPostParameter($key, $value); |
120 |
|
} |
121 |
|
} |
122 |
76 |
if ($headers != array()) { |
123 |
7 |
foreach ($headers as $header) { |
124 |
7 |
$request->setHeader($header[0], $header[1], $header[2]); |
125 |
7 |
} |
126 |
7 |
} |
127 |
76 |
if ($body !== null) { |
128 |
7 |
$request->setBody($body); |
129 |
7 |
} |
130 |
76 |
$code = 0; |
131 |
|
try { |
132 |
76 |
$response = $request->send(); |
133 |
76 |
$code = $response->getStatus(); |
134 |
|
|
135 |
76 |
$this->log->debug($response->getHeader()); |
136 |
76 |
$this->log->debug($response->getBody()); |
137 |
|
|
138 |
76 |
if (self::OK == $code) { |
139 |
75 |
return $response; |
140 |
75 |
} else { |
141 |
|
$eMsg = 'Unexpected HTTP status: ' |
142 |
12 |
. $code . ' ' |
143 |
12 |
. $response->getReasonPhrase(); |
144 |
12 |
$error = $response->getHeader('error'); |
145 |
12 |
if (!is_null($error)) { |
146 |
|
$eMsg .= " ($error)"; |
147 |
|
} |
148 |
|
|
149 |
|
} |
150 |
12 |
} catch (HTTP_Request2_Exception $e) { |
151 |
|
$this->log->warning((string)$e); |
152 |
|
throw new Services_OpenStreetMap_Exception( |
153 |
|
$e->getMessage(), |
154 |
|
$code, |
155 |
|
$e |
156 |
|
); |
157 |
|
} |
158 |
12 |
if ($eMsg != null) { |
159 |
12 |
throw new Services_OpenStreetMap_Exception($eMsg, $code); |
160 |
12 |
} |
161 |
|
} |
162 |
|
|
163 |
|
/** |
164 |
|
* Get HTTP_Request2 instance. |
165 |
|
* |
166 |
|
* @access public |
167 |
|
* @return HTTP_Request2 |
168 |
|
*/ |
169 |
|
public function getRequest() |
170 |
|
{ |
171 |
76 |
return $this->request; |
172 |
|
} |
173 |
|
|
174 |
|
/** |
175 |
|
* Set the HTTP_Request2 instance and return the Services_OpenStreetMap |
176 |
|
* instance. |
177 |
|
* |
178 |
|
* Use this to inject a specific HTTP_Request2 instance. |
179 |
|
* |
180 |
|
* @param HTTP_Request2 $request The HTTP_Request2 instance to set. |
181 |
|
* |
182 |
|
* @return Services_OpenStreetMap |
183 |
|
*/ |
184 |
|
public function setRequest(HTTP_Request2 $request) |
185 |
|
{ |
186 |
102 |
$this->request = $request; |
187 |
102 |
return $this; |
188 |
|
} |
189 |
|
|
190 |
|
/** |
191 |
|
* set Log object |
192 |
|
* |
193 |
|
* @param Log $log Log object |
194 |
|
* |
195 |
|
* @return Services_OpenStreetMap_Transport_HTTP |
196 |
|
*/ |
197 |
|
public function setLog(Log $log) |
198 |
|
{ |
199 |
102 |
$this->log = $log; |
200 |
|
} |
201 |
|
|
202 |
|
/** |
203 |
|
* getObject |
204 |
|
* |
205 |
|
* Returns false if the object is not found |
206 |
|
* |
207 |
|
* @param string $type object type |
208 |
|
* @param mixed $id id of object to retrieve |
209 |
|
* @param mixed $version version of object |
210 |
|
* |
211 |
|
* @return object |
212 |
|
* @throws Services_OpenStreetMap_Exception |
213 |
|
*/ |
214 |
|
public function getObject($type, $id, $version = null) |
215 |
|
{ |
216 |
|
/* |
217 |
|
if (!in_array($type, $this->elements)) { |
218 |
|
throw new Services_OpenStreetMap_Exception( |
219 |
|
sprintf("Invalid Element Type '%s'", $type) |
220 |
|
); |
221 |
|
}*/ |
222 |
|
|
223 |
25 |
$config = $this->getConfig()->asArray(); |
224 |
25 |
$url = $config['server'] |
225 |
|
. 'api/' |
226 |
25 |
. $config['api_version'] |
227 |
25 |
. '/' . $type . '/' |
228 |
25 |
. $id; |
229 |
25 |
if ($version !== null) { |
230 |
1 |
$url .= "/$version"; |
231 |
1 |
} |
232 |
|
try { |
233 |
25 |
$response = $this->getResponse($url); |
234 |
25 |
} catch (Services_OpenStreetMap_Exception $ex) { |
235 |
3 |
$this->log->warning((string)$ex); |
236 |
|
|
237 |
3 |
$code = $ex->getCode(); |
238 |
3 |
if (self::NOT_FOUND == $code) { |
239 |
1 |
return false; |
240 |
2 |
} elseif (self::GONE == $code) { |
241 |
1 |
return false; |
242 |
1 |
} else { |
243 |
1 |
throw $ex; |
244 |
|
} |
245 |
|
} |
246 |
22 |
$class = 'Services_OpenStreetMap_' . ucfirst(strtolower($type)); |
247 |
22 |
$obj = new $class(); |
248 |
22 |
$obj->setXml(simplexml_load_string($response->getBody())); |
249 |
22 |
return $obj; |
250 |
|
} |
251 |
|
|
252 |
|
/** |
253 |
|
* getObjects |
254 |
|
* |
255 |
|
* @param string $type object type |
256 |
|
* @param array $ids ids of objects to retrieve |
257 |
|
* |
258 |
|
* @return void |
259 |
|
* |
260 |
|
*/ |
261 |
|
public function getObjects($type, array $ids) |
262 |
|
{ |
263 |
|
/* |
264 |
|
if (!in_array($type, $this->elements)) { |
265 |
|
throw new Services_OpenStreetMap_Exception('Invalid Element Type'); |
266 |
|
} |
267 |
|
*/ |
268 |
11 |
$config = $this->getConfig(); |
269 |
11 |
$url = $config->getValue('server') |
270 |
|
. 'api/' |
271 |
11 |
. $config->getValue('api_version') |
272 |
11 |
. '/' . $type . 's?' . $type . 's=' |
273 |
11 |
. implode(',', $ids); |
274 |
|
try { |
275 |
11 |
$response = $this->getResponse($url); |
276 |
11 |
} catch (Services_OpenStreetMap_Exception $ex) { |
277 |
4 |
$this->log->warning((string)$ex); |
278 |
4 |
switch ($ex->getCode()) { |
279 |
4 |
case self::NOT_FOUND: |
280 |
4 |
case self::UNAUTHORISED: |
281 |
4 |
case self::GONE: |
282 |
3 |
return false; |
283 |
1 |
default: |
284 |
1 |
throw $ex; |
285 |
1 |
} |
286 |
|
} |
287 |
|
|
288 |
7 |
$class = 'Services_OpenStreetMap_' . ucfirst(strtolower($type)) . 's'; |
289 |
7 |
$obj = new $class(); |
290 |
7 |
if (!is_null($config)) { |
291 |
7 |
$obj->setConfig($config); |
292 |
7 |
} |
293 |
7 |
$obj->setTransport($this); |
294 |
7 |
$sxe = @simplexml_load_string($response->getBody()); |
295 |
7 |
if ($sxe === false) { |
296 |
1 |
$obj->setVal(trim($response->getBody())); |
297 |
1 |
} else { |
298 |
6 |
$obj->setXml($sxe); |
299 |
|
} |
300 |
7 |
return $obj; |
301 |
|
} |
302 |
|
|
303 |
|
/** |
304 |
|
* Set Config object |
305 |
|
* |
306 |
|
* @param Services_OpenStreetMap_Config $config Config settings. |
307 |
|
* |
308 |
|
* @return Services_OpenStreetMap_API_V06 |
309 |
|
*/ |
310 |
|
public function setConfig(Services_OpenStreetMap_Config $config) |
311 |
|
{ |
312 |
102 |
$this->config = $config; |
313 |
|
} |
314 |
|
|
315 |
|
/** |
316 |
|
* Get current Config object |
317 |
|
* |
318 |
|
* @return Services_OpenStreetMap_Config |
319 |
|
*/ |
320 |
|
public function getConfig() |
321 |
|
{ |
322 |
76 |
return $this->config; |
323 |
|
} |
324 |
|
|
325 |
|
/** |
326 |
|
* searchObjects |
327 |
|
* |
328 |
|
* @param string $type object type (e.g. changeset) |
329 |
|
* @param array $criteria array of criterion objects. |
330 |
|
* |
331 |
|
* @return Services_OpenStreetMap_Objects |
332 |
|
*/ |
333 |
|
public function searchObjects($type, array $criteria) |
334 |
|
{ |
335 |
5 |
$query = array(); |
336 |
5 |
foreach ($criteria as $criterion) { |
337 |
5 |
$query[] = $criterion->query(); |
338 |
5 |
} |
339 |
5 |
$config = $this->getConfig(); |
340 |
5 |
$url = $config->getValue('server') |
341 |
|
. 'api/' |
342 |
5 |
. $config->getValue('api_version') |
343 |
5 |
. '/' . $type . 's?' . implode('&', $query); |
344 |
|
try { |
345 |
5 |
$response = $this->getResponse($url); |
346 |
5 |
} catch (Services_OpenStreetMap_Exception $ex) { |
347 |
|
$this->log->warning((string)$ex); |
348 |
|
switch ($ex->getCode()) { |
349 |
|
case self::NOT_FOUND: |
350 |
|
case self::UNAUTHORISED: |
351 |
|
case self::GONE: |
352 |
|
return false; |
353 |
|
default: |
354 |
|
throw $ex; |
355 |
|
} |
356 |
|
} |
357 |
5 |
$class = 'Services_OpenStreetMap_' . ucfirst(strtolower($type)) . 's'; |
358 |
5 |
$obj = new $class(); |
359 |
5 |
$sxe = @simplexml_load_string($response->getBody()); |
360 |
5 |
if ($sxe === false) { |
361 |
|
$obj->setVal(trim($response->getBody())); |
362 |
|
} else { |
363 |
5 |
$obj->setXml($sxe); |
364 |
|
} |
365 |
5 |
return $obj; |
366 |
|
} |
367 |
|
} |