forked from Zverik/Level0
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlevel0l.php
163 lines (157 loc) · 6.17 KB
/
level0l.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
<?php
function data_to_l0l( $data ) {
usort($data, 'userdata_cmp');
$str = '';
$needNewline = false;
$tmpid = 0;
foreach( $data as $obj ) {
if( !isset($obj['type']) || !isset($obj['id']) ) {
echo "fail object $tmpid: ";
print_r($obj);
}
$tmpid++;
if( $needNewline || $obj['type'] != 'node' )
$str .= "\n";
$needNewline = $obj['type'] != 'node' || count($obj['tags']) > 0 || isset($obj['conflict']);
if( isset($obj['conflict']) ) {
$conflict = data_to_l0l(array($obj['conflict']));
$conflict = _('Conflict! Your edits to the old version are saved in this comment.\nPlease make appropriate changes and remove \'!\' character from the entity header.')."\n".$conflict;
$conflict = preg_replace('/^/m', '# ', $conflict);
$str .= $conflict.'!';
}
if( isset($obj['action']) && $obj['action'] == 'delete' )
$str .= '-';
$str .= $obj['type'];
if( $obj['id'] != 0 ) {
$str .= ' '.$obj['id'];
if( isset($obj['version']) )
$str .= '.'.$obj['version'];
}
if( $obj['type'] == 'node' && isset($obj['lat']) && isset($obj['lon']) )
$str .= ': '.$obj['lat'].', '.$obj['lon'];
$str .= "\n";
foreach( $obj['tags'] as $k => $v ) {
$str .= sprintf(" %s = %s\n", str_replace('=', '\\=', $k), $v);
}
if( $obj['type'] == 'way' && count($obj['nodes']) > 0 )
foreach( $obj['nodes'] as $nd )
$str .= ' nd '.$nd."\n";
if( $obj['type'] == 'relation' && count($obj['members']) > 0 )
foreach( $obj['members'] as $m )
$str .= sprintf(" %s %s%s\n", $m['type'] == 'node' ? 'nd' : ($m['type'] == 'way' ? 'wy' : 'rel'), $m['id'], strlen($m['role']) > 0 ? ' '.$m['role'] : '');
}
return $str;
}
// Parses level0l into $userdata
function l0l_to_data( $str ) {
global $validation;
$lines = explode("\n", $str);
$data = array();
$cur = false;
$ln = 0;
$found_changeset = false;
foreach( $lines as $line ) {
$ln++;
if( !strlen(trim($line)) || substr($line, 0, 1) == '#' )
continue;
if( preg_match('/^(!)?(-)?(node|way|relation|changeset)(?:\\s+(-?[0-9]+)(?:\\.([0-9]+))?)?(?:\\s*:\\s*(-?\\d{1,2}(?:\.\\d+)?)\\s*,\\s*(-?\\d{1,3}(?:\\.\\d+)?))?\\s*(?:#.*)?$/', $line, $m) ) {
if( $cur ) {
validate_entity($cur, $ln - 1);
$data[] = $cur;
}
$cur = array('type' => $m[3], 'id' => (count($m) > 4 && strlen($m[4]) > 0 ? $m[4] : 0));
if( $m[1] === '!' )
$validation[] = array(true, $ln, sprintf(_('Please resolve conflict of %s %s'), $cur['type'], $cur['id']));
if( $m[2] === '-' ) {
if( $cur['id'] > 0 )
$cur['action'] = 'delete';
else
$validation[] = array(true, $ln, _('Deleting an unsaved object'));
}
if( $cur['type'] == 'changeset' && $cur['id'] <= 0 ) {
if( $found_changeset )
$validation[] = array(true, $ln, _('There can be only one changeset metadata'));
else
$found_changeset = true;
}
if( count($m) > 5 && strlen($m[5]) > 0 )
$cur['version'] = $m[5];
if( count($m) > 7 && strlen($m[6]) > 0 && strlen($m[7]) > 0 ) {
if( $cur['type'] == 'node' ) {
$cur['lat'] = $m[6];
$cur['lon'] = $m[7];
} else
$validation[] = array(false, $ln, sprintf(_('Coordinates specified for %s %d'), $cur['type'], $cur['id']));
} elseif( $cur['type'] == 'node' && $m[2] !== '-' )
$validation[] = array(true, $ln, _('Node without coordinates'));
$cur['tags'] = array();
if( $cur['type'] == 'way' )
$cur['nodes'] = array();
elseif( $cur['type'] == 'relation' )
$cur['members'] = array();
} elseif( $cur ) {
if( preg_match('/^\\s*(nd|wy|rel)\\s+(-?\\d+)(?:\\s+(.+?))?\\s*$/', $line, $m) ) {
if( $cur['type'] == 'node' ) {
$validation[] = array(true, $ln, _('A node cannot have member objects'));
} elseif( $cur['type'] == 'way' ) {
if( $m[1] == 'nd' ) {
$cur['nodes'][] = $m[2];
if( count($m) > 3 && strlen($m[3]) > 0 )
$validation[] = array(false, $ln, _('Role name specified for a way node'));
} else
$validation[] = array(true, $ln, _('Ways cannot have members besides nodes'));
} elseif( $cur['type'] == 'relation' ) {
$cur['members'][] = array('type' => ($m[1] == 'nd' ? 'node' : ($m[1] == 'wy' ? 'way' : 'relation')), 'id' => $m[2], 'role' => (count($m) > 3 ? $m[3] : ''));
}
} elseif( preg_match('/^\\s*([^=]*?(?:\\\\=[^=]*?)*)\\s*=\\s*(.+?)\\s*$/', $line, $m) ) {
// regular expression is unreliable, find equals sign by hand
$eq = 1;
while( $eq < strlen($line) && (substr($line, $eq, 1) != '=' || substr($line, $eq-1, 1) == '\\') )
$eq++;
if( $eq < strlen($line) ) {
$key = str_replace('\\=', '=', trim(substr($line, 0, $eq)));
$value = trim(substr($line, $eq+1));
if( !isset($cur['tags'][$key]) )
$cur['tags'][$key] = $value;
else
$validation[] = array(true, $ln, _('Duplicated tag'));
} else
$validation[] = array(false, $ln, sprintf(_('Unknown content while parsing %s %s'), $cur['type'], $cur['id']));
} else
$validation[] = array(false, $ln, sprintf(_('Unknown content while parsing %s %s'), $cur['type'], $cur['id']));
} else
$validation[] = array(false, $ln, _('Unknown and unparsed content found'));
}
if( $cur ) {
validate_entity($cur, $ln);
$data[] = $cur;
}
return $data;
}
function validate_entity( $obj, $ln ) {
global $validation;
$is_new = $obj['id'] <= 0;
$is_deleted = isset($obj['action']) && $obj['action'] == 'delete';
if( $is_new || !$is_deleted ) {
if( $obj['type'] == 'way' && count($obj['nodes']) < 2 )
$validation[] = array(true, $ln, sprintf(_('Way %d has less than two nodes'), $obj['id']));
elseif( $obj['type'] == 'relation' && !count($obj['members']) )
$validation[] = array(true, $ln, sprintf(_('Relation %d has no members'), $obj['id']));
}
}
// Merges changes into l0l text
function l0l_merge( $str, $added, $modified ) {
$str = data_to_l0l($added)."\n".$str;
// todo: modify modified
return $str;
}
// a function to be used in usort($userdata, 'userdata_cmp')
function userdata_cmp($a, $b) {
$typea = $a['type'] == 'node' ? (count($a['tags']) ? 0 : 4) : ($a['type'] == 'way' ? 1 : 2);
$typeb = $b['type'] == 'node' ? (count($b['tags']) ? 0 : 4) : ($b['type'] == 'way' ? 1 : 2);
if( $typea < $typeb ) return -1;
if( $typea > $typeb ) return 1;
$idd = $a['id'] - $b['id'];
return $idd > 0 ? 1 : ($idd < 0 ? -1 : 0);
}
?>