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