forked from cyberwolf/cnapi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cnapi.request.inc
272 lines (230 loc) · 8.42 KB
/
cnapi.request.inc
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
<?php
function _cnapi_default_values($key = NULL, $namespace = NULL) {
switch ($namespace) {
case 'event':
$defaults = variable_get('cnapi_defaults_events', array('pagelength' => -1, 'sort' => -1));
break;
case 'production':
$defaults = variable_get('cnapi_defaults_productions', array('pagelength' => -1, 'sort' => -1));
break;
case 'actor':
$defaults = variable_get('cnapi_defaults_actors', array('pagelength' => -1, 'sort' => -1));
break;
default:
$defaults = variable_get('cnapi_defaults', array('pagelength' => CNAPI_DEFAULT_PAGELENGTH, 'sort' => CNAPI_DEFAULT_SORT));
break;
}
if (!$key) {
return $defaults;
}
else {
return $defaults[$key];
}
}
// only supports scalar defaults
// stuff like pagelength, page and sort are always specified although not necessary to get a meaningful cache id (cid still works if defaults change)
function cnapi_request_add_defaults(&$request) {
$defaults = _cnapi_query_defaults($request);
// setting defaults
foreach ($defaults as $key => $value) {
if (!isset($request['query'][$key])) {
$request['query'][$key] = $value;
}
}
}
function cnapi_request_remove_defaults(&$request) {
$defaults = _cnapi_query_defaults($request);
// setting defaults
foreach ($defaults as $key => $value) {
if (isset($request['query'][$key]) && $request['query'][$key] == $value) {
unset($request['query'][$key]);
}
}
}
function _cnapi_query_defaults($request) {
// format
$defaults['format'] = 'xml';
// api key
$defaults['key'] = trim(variable_get('cnapi_api_key', ''));
// detail
if ($request['action'] == 'detail' && in_array($request['type'], array('event', 'production'))) {
$defaults['relatedevents'] = 'id';
}
// lists
if (in_array($request['action'], array('list_detail', 'list_summary'))) {
// page
$defaults['page'] = 1;
// calculating defaults
$defaults = array_merge($defaults, _cnapi_default_values());
foreach (array('event', 'production', 'actor') as $type) {
if ($request['type'] == $type) {
$namespace_defaults = array();
foreach (_cnapi_default_values(NULL, $type) as $key => $val) {
if ($val != -1) {
$namespace_defaults[$key] = $val;
}
}
$defaults = array_merge($defaults, $namespace_defaults);
}
}
}
drupal_alter('cnapi_request_defaults', $defaults, $request);
return $defaults;
}
// cnapi_request_clean is very important in case of report because cache id depends on it, otherwise we get a different cache per page
// Does a best effort. : cleaning up for report, detail, ... but for "query" we don't care
function cnapi_request_clean(&$request) {
$valid_query_detail = array('key', 'cdbid', 'relatedevents');
$invalid_query_report = array('page', 'pagelength', 'sort');
// clean detail requests
if ($request['action'] == 'detail') {
$request['query'] = array_intersect_key($request['query'], array_flip($valid_query_detail));
}
// clean report requests
elseif ($request['action'] == 'report') {
$request['query'] = array_diff_key($request['query'], array_flip($invalid_query_report));
}
}
function cnapi_request_validate($request) {
$valid_actions = array('list_detail', 'list_summary', 'detail', 'report');
$valid_types = array('event', 'production', 'actor');
// all requests should have a key
if (!$request['query']['key']) {
return FALSE;
}
// check if action is valid
if (!in_array($request['action'], $valid_actions)) {
return FALSE;
}
// check if type is valid
if (!in_array($request['type'], $valid_types)) {
return FALSE;
}
// reports not valid on actors
if ($request['type'] == 'actor' && $request['action'] == 'report') {
return FALSE;
}
// validate $query keys for list, summary and report
$valid_queries_common = array('key', 'q', 'k', 'cdbid', 'changedsince', 'deletedsince', 'hasimage', 'zip', 'city', 'cityid', 'regio', 'latlng', 'format', 'locationtype', 'sort', 'page', 'pagelength');
$valid_queries_events_productions = array('locationkeyword', 'organiserkeyword', 'organiser', 'agebetween', 'age', 'isfree', 'isparent', 'permanent', 'temporary', 'location', 'agefrom', 'organizer', 'type', 'thema', 'targetaudience', 'facility', 'publicscope', 'eventtype', 'actortype', 'municipal', 'ipe', 'misc', 'heading', 'daterange', 'date', 'datetype');
if (in_array($request['action'], array('list_detail', 'list_summary', 'report'))) {
if ($request['type'] == 'actor') {
$valid_queries = $valid_queries_common;
}
elseif (in_array($request['type'], array('event', 'production'))) {
$valid_queries = array_merge($valid_queries_common, $valid_queries_events_productions);
}
$diff = array_diff(array_keys($request['query']), $valid_queries);
if (!empty($diff)) {
return FALSE;
}
}
// providing a hook so other modules can restrict access to certain queries
foreach (module_implements('cnapi_request_validate') as $module) {
if (!module_invoke($module, 'cnapi_request_validate')) {
return FALSE;
}
}
return TRUE;
}
function cnapi_request_sort(&$request) {
ksort($request); // sorting $request by order 'action', 'type', 'query'
ksort($request['query']); // sorting all queries
// sorting all multivalue queries
foreach ($request['query'] as $key => $value) {
$parts = explode(';', $value);
asort($parts);
$request['query'][$key] = implode(';', $parts);
}
}
/**
* Calculate a hash value of an API request array.
*
* Uniquely identifies an API request. Requests are identical if they have the same action, type, query. Order of the query parts and values is ignored (@see cnapi_query_hash).
*
* @param $request
* An API request array (@see _cnapi_get).
*
* @return
* The hash value of the API request array.
*/
function cnapi_request_hash($request) {
cnapi_request_clean($request);
cnapi_request_sort($request);
return md5(serialize($request));
}
/**
* Calculate a hash value for the 'query' of an API request array.
*
* Uniquely identifies a 'query' of an API request. Order of the query parts and values is ignored. So array('page' => 1, 'q' => 'Some query', 'heading' => '1;2;3') has the same hash as array('q' => 'Some query', 'page' => 1, 'heading' => '2;3,1').
*
* @param $request
* An API request array (@see _cnapi_get).
*
* @return
* The hash value of the 'query' of the API request array.
*/
function cnapi_query_hash($request) {
cnapi_request_clean($request);
cnapi_request_sort($request);
return md5(serialize($request['query']));
}
function cnapi_base_query_hash($request) {
$base_request = $request;
unset($base_request['query']['page']);
unset($base_request['query']['pagelength']);
unset($base_request['query']['sort']);
unset($base_request['options']['parse_geo']);
return cnapi_query_hash($base_request);
}
function cnapi_url_a2p($url = '') {
$request = array('action' => '', 'type' => '', 'query' => array());
$url = ltrim($url, '/');
extract(parse_url($url));
// usually the url $query is the $query
parse_str($query, $request['query']);
// list, summary and report
$match = array();
if (preg_match_all('/^(events|actors|productions)\/(search|xmlview|report)$/i', $path, $match)) {
$mapping = array(
'search' => 'list_summary',
'xmlview' => 'list_detail',
'report' => 'report',
);
$action = $match[2][0];
$request['action'] = $mapping[$action];
$request['type'] = substr($match[1][0], 0, -1);
}
// details
$match = array();
if (preg_match_all('/^(event|actor|production)\/([0-9a-zA-Z\-]*)$/i', $path, $match)) {
$request['action'] = 'detail';
$request['type'] = $match[1][0];
$request['query']['cdbid'] = $match[2][0];
}
cnapi_request_clean($request);
return $request;
}
function cnapi_url_p2a($request = array()) {
cnapi_request_clean($request);
$path = '';
switch ($request['action']) {
case 'detail':
$path = $request['type'] . '/' . $request['query']['cdbid'];
unset($request['query']['cdbid']);
break;
case 'list_detail':
case 'list_summary':
case 'report':
$mapping = array(
'list_summary' => 'search',
'list_detail' => 'xmlview',
'report' => 'report',
);
$action = $mapping[$request['action']];
$path = $request['type'] . 's/' . $action;
}
$qs = http_build_query($request['query'], '', '&');
if (strlen($qs) > 0) $qs = '?' . $qs;
return $path . $qs;
}