Esempio n. 1
0
function parse_osm_xml($uri)
{
    global $messages;
    $r = new XMLReader();
    if (!$r->open($uri, 'utf-8')) {
        $messages[] = _('Failed to open XML stream');
        return;
    }
    $result = array();
    $mode = false;
    $cur = array();
    while ($r->read()) {
        if ($r->nodeType == XMLReader::ELEMENT) {
            if ($r->name == 'modify' || $r->name == 'create' || $r->name == 'delete') {
                $mode = $r->name;
            } elseif ($r->name == 'node' || $r->name == 'way' || $r->name == 'relation' || $r->name == 'changeset') {
                $id = $r->getAttribute('id');
                if ($id === null) {
                    $id = 0;
                }
                if (is_pint($id)) {
                    $cur['type'] = $r->name;
                    $cur['id'] = $id;
                    $action = $mode ? $mode : $r->getAttribute('action');
                    if ($action) {
                        $cur['action'] = $action;
                    }
                    // user, uid, visible, changeset, timestamp
                    $version = $r->getAttribute('version');
                    $user = $r->getAttribute('user');
                    $uid = $r->getAttribute('uid');
                    $visible = $r->getAttribute('visible');
                    $changeset = $r->getAttribute('changeset');
                    $timestamp = $r->getAttribute('timestamp');
                    if (is_pint($version, true)) {
                        $cur['version'] = $version;
                    }
                    if ($user !== null && strlen($user) > 0) {
                        $cur['user'] = $user;
                    }
                    if (is_pint($uid, true)) {
                        $cur['uid'] = $uid;
                    }
                    if (is_pint($changeset, true)) {
                        $cur['changeset'] = $changeset;
                    }
                    if ($timestamp != null && strlen($timestamp) > 10) {
                        $cur['timestamp'] = $timestamp;
                    }
                    // parse?
                    if ($visible === 'false') {
                        $cur['deleted'] = true;
                    }
                    $cur['tags'] = array();
                    if ($r->name == 'node') {
                        $lat = $r->getAttribute('lat');
                        $lon = $r->getAttribute('lon');
                        if (is_numeric($lat) && is_numeric($lon)) {
                            $cur['lat'] = $lat;
                            $cur['lon'] = $lon;
                        }
                    } elseif ($r->name == 'way') {
                        $cur['nodes'] = array();
                    } elseif ($r->name == 'relation') {
                        $cur['members'] = array();
                    }
                }
            } elseif ($r->name == 'tag') {
                $key = $r->getAttribute('k');
                $value = $r->getAttribute('v');
                if ($key !== null && $value !== null) {
                    $tkey = hard_trim($key);
                    $tvalue = hard_trim($value);
                    if (strlen($tkey) > 0 && strlen($tvalue) > 0) {
                        $cur['tags'][$tkey] = $tvalue;
                    }
                    if (!isset($cur['action']) && ($key !== $tkey || $value !== $tvalue)) {
                        $cur['action'] = 'modify';
                    }
                }
            } elseif ($r->name == 'nd') {
                $ref = $r->getAttribute('ref');
                if (is_pint($ref)) {
                    $cur['nodes'][] = $ref;
                }
            } elseif ($r->name == 'member') {
                $mtype = $r->getAttribute('type');
                $mref = $r->getAttribute('ref');
                $mrole = $r->getAttribute('role');
                if ($mtype !== null && preg_match('/^(?:node|way|relation)$/', $mtype) && is_pint($mref)) {
                    $member = array('type' => $mtype, 'id' => $mref);
                    $member['role'] = $mrole === null ? '' : $mrole;
                    $cur['members'][] = $member;
                }
            }
        }
        if ($r->nodeType == XMLReader::END_ELEMENT || $r->isEmptyElement) {
            if ($r->name == $mode) {
                $mode = false;
            } elseif (isset($cur['type']) && $r->name == $cur['type']) {
                if (isset($cur['version']) && $cur['version'] > 1) {
                    // if $result contains older version, remove it
                    for ($i = 0; $i < count($result); $i++) {
                        if ($result[$i]['type'] == $cur['type'] && $result[$i]['id'] == $cur['id'] && (!isset($result['version']) || $result['version'] <= $cur['version'])) {
                            array_splice($result, $i, 1);
                            break;
                        }
                    }
                }
                $result[] = $cur;
                $cur = array();
            }
        }
        if (count($result) == MAX_REQUEST_OBJECTS) {
            $messages[] = sprintf(_('Download is incomplete, maximum of %d objects has been reached'), MAX_REQUEST_OBJECTS);
            break;
        }
    }
    $r->close();
    return renumber_created($result);
}
Esempio n. 2
0
function update_data($data)
{
    global $basedata, $userdata, $messages, $added, $modified;
    // arrays for merging
    if (!isset($added) || !isset($modified)) {
        $added = array();
        $modified = array();
    }
    if (count($userdata)) {
        $data = renumber_created($data, $userdata);
    }
    // nb: this is already done in osmapi.php
    foreach ($data as $obj) {
        $objnv = strip_version($obj);
        if ($obj['type'] == 'changeset') {
            // check that created changeset metadata is not duplicated
            if ($obj['id'] > 0) {
                $found = false;
                foreach ($userdata as $obj) {
                    if ($obj['type'] == 'changeset' && $obj['id'] <= 0) {
                        $found = true;
                        break;
                    }
                }
                if ($found) {
                    $messages[] = _('There can be only one changeset metadata') . '.';
                    continue;
                }
            }
            $userdata[] = $objnv;
            $added[] = $objnv;
        } elseif ($obj['id'] <= 0 || isset($obj['action']) && $obj['action'] == 'create') {
            // created objects go straight to userdata
            $userdata[] = $objnv;
            $added[] = $objnv;
        } else {
            // modify, delete or base
            if (!isset($obj['version'])) {
                $messages[] = sprintf(_('No version for object %s %s.'), $obj['type'], $obj['id']);
                continue;
            }
            if (isset($obj['action']) && strlen($obj['action']) > 0) {
                // for deleted and modified save only version
                $res = array('type' => $obj['type'], 'id' => $obj['id'], 'version' => $obj['version'], 'complete' => false);
            } else {
                $res = $obj;
                $res['complete'] = true;
            }
            // $res goes to basedata, $obj should be merged with userdata
            $pk = $res['type'] . $res['id'];
            $version_diff = $res['version'] - (isset($basedata[$pk]) ? $basedata[$pk]['version'] : 0);
            if (!isset($basedata[$pk]) || !$version_diff) {
                if (!isset($basedata[$pk]) || !$basedata[$pk]['complete']) {
                    $basedata[$pk] = $res;
                }
                // userdata: if exists and modified, leave current version, otherwise replace
                $found = false;
                for ($i = 0; $i < count($userdata); $i++) {
                    if ($userdata[$i]['type'] == $res['type'] && $userdata[$i]['id'] == $res['id']) {
                        $found = true;
                        if (!is_modified($userdata[$i])) {
                            // should we replace it with the new version? idk.
                            // $userdata[$i] = $objnv;
                            // $modified[] = $objnv;
                        }
                    }
                }
                if (!$found) {
                    $userdata[] = $objnv;
                    $added[] = $objnv;
                }
            } elseif ($version_diff < 0) {
                // it's really old, skip it
                $messages[] = sprintf(_('Found older version of %s %s: %d instead of %d.'), $res['type'], $res['id'], $res['version'], $basedata[$pk]['version']);
            } else {
                $basedata[$pk] = $res;
                // userdata: if exists and modified, then conflict!
                $found = false;
                for ($i = 0; $i < count($userdata); $i++) {
                    if ($userdata[$i]['type'] == $res['type'] && $userdata[$i]['id'] == $res['id']) {
                        $found = true;
                        if (is_modified($userdata[$i])) {
                            $objnv['conflict'] = $userdata[$i];
                            $userdata[$i] = $objnv;
                            $modified[] = $objnv;
                        }
                    }
                }
                if (!$found) {
                    $userdata[] = $objnv;
                    $added[] = $objnv;
                }
            }
        }
    }
}