1 : <?php
2 : /**
3 : * Object.php
4 : * 26-Apr-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 Object.php
14 : */
15 :
16 : /**
17 : * Services_Openstreetmap_Object
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 Object.php
24 : */
25 : class Services_Openstreetmap_Object
26 : {
27 : protected $xml = null;
28 :
29 : /**
30 : * Array of tags in key/value format
31 : *
32 : * @var array
33 : */
34 : protected $tags = array();
35 :
36 : protected $id = null;
37 :
38 : protected $transport = null;
39 :
40 : protected $config = null;
41 :
42 : /**
43 : * type of object
44 : *
45 : * @var string
46 : */
47 : protected $type = null;
48 :
49 : protected $obj = null;
50 :
51 : protected $dirty = false;
52 :
53 : protected $action = null;
54 :
55 : protected $changesetId = null;
56 :
57 : /**
58 : * getXml
59 : *
60 : * @return string
61 : */
62 : public function getXml()
63 : {
64 0 : return $this->xml;
65 : }
66 :
67 : /**
68 : * If modified, return the osmChangeXML for the object, otherwise the defining
69 : * XML.
70 : *
71 : * @return string
72 : * @link http://wiki.openstreetmap.org/wiki/OsmChange
73 : */
74 : public function __toString()
75 : {
76 0 : $changeXML = $this->getOsmChangeXml();
77 0 : if (is_null($changeXML)) {
78 0 : return '' . $this->getXml();
79 : } else {
80 0 : return $changeXML;
81 : }
82 : }
83 :
84 : /**
85 : * setXml
86 : *
87 : * @param SimpleXMLElement $xml OSM XML
88 : *
89 : * @return void
90 : */
91 : public function setXml(SimpleXMLElement $xml)
92 : {
93 10 : $this->xml = $xml->saveXml();
94 10 : $obj = $xml->xpath('//' . $this->getType());
95 10 : foreach ($obj[0]->children() as $child) {
96 10 : $key = (string) $child->attributes()->k;
97 10 : if ($key != '') {
98 9 : $this->tags[$key] = (string) $child->attributes()->v;
99 9 : }
100 10 : }
101 10 : $this->obj = $obj;
102 10 : return $this;
103 : }
104 :
105 : /**
106 : * Store a specified value.
107 : *
108 : * @param string $value Most likely an id value, returned from the server.
109 : *
110 : * @return void
111 : */
112 : public function setVal($value)
113 : {
114 0 : $this->xml = $value;
115 0 : return $this;
116 : }
117 :
118 : /**
119 : * Set the Changeset Id for this object.
120 : *
121 : * @param integer $id Changeset Id (numeric)
122 : *
123 : * @return Services_Openstreetmap_Object
124 : */
125 : public function setChangesetId($id)
126 : {
127 0 : $this->changesetId = $id;
128 0 : return $this;
129 : }
130 :
131 : /**
132 : * Generate and return the OsmChange XML required to record the changes
133 : * made to the object in question.
134 : *
135 : * @return string
136 : * @link http://wiki.openstreetmap.org/wiki/OsmChange
137 : */
138 : public function getOsmChangeXml()
139 : {
140 0 : $type = $this->getType();
141 0 : if ($this->dirty) {
142 0 : $version = $this->getVersion();
143 0 : $version++;
144 0 : $domd = new DomDocument();
145 0 : $domd->loadXml($this->getXml());
146 0 : $xpath = new DomXPath($domd);
147 0 : $nodelist = $xpath->query("//{$type}");
148 0 : $nodelist->item(0)->setAttribute('action', $this->action);
149 0 : $nodelist->item(0)->setAttribute('id', $this->getId());
150 :
151 0 : if (!is_null($this->changesetId)) {
152 0 : $nodelist->item(0)->setAttribute('changeset', $this->changesetId);
153 0 : }
154 0 : $tags = $xpath->query("//{$type}/tag");
155 :
156 0 : $set = array();
157 0 : for ($i = 0; $i < $tags->length; $i++) {
158 0 : $key = $tags->item($i)->getAttribute('k');
159 0 : $val = $tags->item($i)->getAttribute('v');
160 0 : $set[$key] = $val;
161 0 : }
162 :
163 0 : $diff = array_diff($this->getTags(), $set);
164 :
165 : // Remove existing tags
166 0 : for ($i = 0; $i < $tags->length; $i++) {
167 0 : $rkey = $tags->item($i)->getAttribute('k');
168 0 : if (isset($diff[$rkey])) {
169 0 : $nodelist->item(0)->removeChild($tags->item($i));
170 0 : }
171 0 : }
172 :
173 0 : foreach ($diff as $key=>$value) {
174 0 : $new = $domd->createElement('tag');
175 0 : $new->setAttribute('k', $key);
176 0 : $new->setAttribute('v', $value);
177 0 : $nodelist->item(0)->appendChild($new);
178 0 : }
179 :
180 0 : $xml = $domd->saveXml($nodelist->item(0));
181 0 : $xml = "<{$this->action}>{$xml}</{$this->action}>";
182 0 : return $this->osmChangeXml($xml);
183 :
184 0 : } elseif ($this->action == 'delete') {
185 0 : $xml = null;
186 0 : $domd = new DomDocument();
187 0 : $domd->loadXml($this->getXml());
188 0 : $xpath = new DomXPath($domd);
189 0 : $n = $xpath->query("//{$type}");
190 0 : $version = $this->getVersion();
191 0 : $version++;
192 0 : if (!is_null($this->changesetId)) {
193 0 : $n->item(0)->setAttribute('changeset', $this->changesetId);
194 0 : }
195 0 : $n->item(0)->setAttribute('action', 'delete');
196 0 : $xml = $domd->saveXml($n->item(0));
197 0 : return $this->osmChangeXml("<delete>{$xml}</delete>");
198 : }
199 0 : }
200 :
201 : /**
202 : * Amend changeXML with specific updates as appropriate.
203 : *
204 : * @param string $xml OsmChange XML as generated by getOsmChangeXml
205 : *
206 : * @return string
207 : * @see getOsmChangeXml
208 : * @link http://wiki.openstreetmap.org/wiki/OsmChange
209 : */
210 : public function osmChangeXml($xml)
211 : {
212 0 : return $xml;
213 : }
214 :
215 : /**
216 : * Retrieve the id of the object in question.
217 : *
218 : * @return integer id of the object
219 : */
220 : public function getId()
221 : {
222 2 : if (!is_null($this->id)) {
223 1 : return $this->id;
224 : }
225 :
226 1 : $attribs = $this->getAttributes();
227 1 : if (!is_null($attribs)) {
228 1 : return (integer) $attribs->id;
229 : }
230 0 : }
231 :
232 : /**
233 : * Set the id value of the object in question.
234 : *
235 : * <pre>
236 : * $obj->setId($id)->...
237 : * </pre>
238 : *
239 : * @param integer $value new id of the object
240 : *
241 : * @return Services_Openstreetmap_Object
242 : */
243 : public function setId($value)
244 : {
245 1 : $this->id = $value;
246 1 : return $this;
247 : }
248 :
249 : /**
250 : * Retrieve the uid of the object in question.
251 : *
252 : * @return integer uid of the object
253 : */
254 : public function getUid()
255 : {
256 1 : $attribs = $this->getAttributes();
257 1 : if (!is_null($attribs)) {
258 1 : return (integer) $attribs->uid;
259 : }
260 0 : }
261 :
262 : /**
263 : * Retrieve the user (creator/editor) of the object in question.
264 : *
265 : * @return string user of the object
266 : */
267 : public function getUser()
268 : {
269 1 : $attribs = $this->getAttributes();
270 1 : if (!is_null($attribs)) {
271 1 : return (string) $attribs->user;
272 : }
273 0 : }
274 :
275 : /**
276 : * Retrieve the version of the object in question
277 : *
278 : * @return string version of the object
279 : */
280 : public function getVersion()
281 : {
282 1 : $attribs = $this->getAttributes();
283 1 : if (!is_null($attribs)) {
284 1 : return (integer) $attribs->version;
285 : }
286 0 : }
287 :
288 : /**
289 : * Return the attributes set for this object in question.
290 : *
291 : * @return string getAttributes()
292 : */
293 : public function getAttributes()
294 : {
295 :
296 5 : if (is_null($this->obj[0])) {
297 0 : return null;
298 : }
299 5 : return $this->obj[0]->attributes();
300 : }
301 :
302 : /**
303 : * Return the tags set for this object in question.
304 : *
305 : * @return array tags
306 : */
307 : public function getTags()
308 : {
309 5 : return $this->tags;
310 : }
311 :
312 :
313 : /**
314 : * Return value of specified tag as set against this object.
315 : * If tag isn't set, return null.
316 : *
317 : * @param string $key Key value, For example, 'amenity', 'highway' etc
318 : *
319 : * @return string
320 : */
321 : public function getTag($key)
322 : {
323 1 : if (isset($this->tags[$key])) {
324 1 : return $this->tags[$key];
325 : } else {
326 0 : return null;
327 : }
328 : }
329 :
330 : /**
331 : * Return which type of object this is.
332 : *
333 : * @return string type
334 : */
335 : public function getType()
336 : {
337 10 : return $this->type;
338 : }
339 :
340 : /**
341 : * Get each distinct version of an object.
342 : *
343 : * @return Services_Openstreetmap_Objects
344 : */
345 : public function history()
346 : {
347 0 : $transport = null;
348 0 : $type = $this->getType();
349 0 : $id = $this->getId();
350 0 : $config = $this->getConfig();
351 0 : $url = $config->getValue('server')
352 : . 'api/'
353 0 : . $config->getValue('api_version')
354 0 : . "/$type/$id/history";
355 0 : $class = 'Services_Openstreetmap_' . ucfirst($type) . 's';
356 0 : $transport = $this->getTransport();
357 0 : $response = $transport->getResponse($url);
358 0 : $obj = new $class();
359 0 : $sxe = @simplexml_load_string($response->getBody());
360 0 : if ($sxe === false) {
361 0 : $obj->setVal(trim($response->getBody()));
362 0 : } else {
363 0 : $obj->setXml($sxe);
364 : }
365 0 : return $obj;
366 : }
367 :
368 : /**
369 : * Get all relations referring to the object in question.
370 : *
371 : * @return Services_Openstreetmap_Relations
372 : */
373 : public function getRelations()
374 : {
375 1 : $type = $this->getType();
376 1 : $id = $this->getId();
377 1 : $config = $this->getConfig();
378 1 : $url = $config->getValue('server')
379 : . 'api/'
380 1 : . $config->getValue('api_version')
381 1 : . "/$type/$id/relations";
382 1 : $response = $this->getTransport()->getResponse($url);
383 1 : $obj = new Services_Openstreetmap_Relations();
384 1 : $sxe = @simplexml_load_string($response->getBody());
385 1 : if ($sxe === false) {
386 0 : $obj->setVal(trim($response->getBody()));
387 0 : } else {
388 1 : $obj->setXml($sxe);
389 : }
390 1 : return $obj;
391 : }
392 :
393 : /**
394 : * setTag
395 : *
396 : * <pre>
397 : * $obj->setTag('key', 'value')->setTag(...);
398 : * </pre>
399 : *
400 : * @param mixed $key key
401 : * @param mixed $value value
402 : *
403 : * @return void
404 : */
405 : public function setTag($key, $value)
406 : {
407 2 : if (is_null($this->action)) {
408 1 : if ($this->getId() < 0) {
409 1 : $this->action = 'create';
410 1 : } else {
411 0 : $this->action = 'modify';
412 : }
413 1 : }
414 2 : $this->dirty = true;
415 2 : $this->tags[$key] = $value;
416 2 : return $this;
417 : }
418 :
419 : /**
420 : * Mark the object as deleted.
421 : *
422 : * <pre>
423 : * $obj->delete();
424 : * </pre>
425 : *
426 : * @return void
427 : */
428 : public function delete()
429 : {
430 0 : $this->action = 'delete';
431 0 : return $this;
432 : }
433 :
434 : /**
435 : * Set Config object
436 : *
437 : * @param Services_Openstreetmap_Config $config Config object
438 : *
439 : * @return Services_Openstreetmap_Changeset
440 : */
441 : public function setConfig(Services_Openstreetmap_Config $config)
442 : {
443 10 : $this->config = $config;
444 10 : return $this;
445 : }
446 :
447 : /**
448 : * Get current Config object
449 : *
450 : * @return Services_Openstreetmap_Config
451 : */
452 : public function getConfig()
453 : {
454 1 : return $this->config;
455 : }
456 :
457 : /**
458 : * Set the Transport instance.
459 : *
460 : * @param Services_Openstreetmap_Transport $transport Transport instance.
461 : *
462 : * @return Services_Openstreetmap_Config
463 : */
464 : public function setTransport($transport)
465 : {
466 10 : $this->transport = $transport;
467 10 : return $this;
468 : }
469 :
470 : /**
471 : * Retrieve the current Transport instance.
472 : *
473 : * @return Services_Openstreetmap_Transport.
474 : */
475 : public function getTransport()
476 : {
477 1 : return $this->transport;
478 : }
479 : }
480 :
481 : // vim:set et ts=4 sw=4:
482 : ?>
|