Blame view

php/epntap.php 9.77 KB
8a0f1e9e   Nathanael Jourdane   Add autocompletio...
1
<?php
68664dca   Nathanael Jourdane   make epntap php f...
2

49401187   Nathanael Jourdane   epntap: Do not us...
3
include(realpath(dirname(__FILE__) . "/config.php"));
49401187   Nathanael Jourdane   epntap: Do not us...
4
5
include(CLASSPATH . "VOTableMgr.php");

8c2fa14d   Nathanael Jourdane   Update services g...
6
$action = preg_replace("/[^a-zA-Z]+/", "", filter_var($_GET['action'], FILTER_SANITIZE_STRING));
68664dca   Nathanael Jourdane   make epntap php f...
7
8
9

switch ($action) {
	case 'resolver':
50dd7220   Nathanael Jourdane   epntap.php works ...
10
		$response = resolver();
68664dca   Nathanael Jourdane   make epntap php f...
11
		break;
8c2fa14d   Nathanael Jourdane   Update services g...
12
	case 'getServices':
50dd7220   Nathanael Jourdane   epntap.php works ...
13
		$response = getServices();
68664dca   Nathanael Jourdane   make epntap php f...
14
		break;
853c8154   Nathanael Jourdane   Init start/stop d...
15
16
	case 'updateNbResults':
		$response = updateNbResults();
8c2fa14d   Nathanael Jourdane   Update services g...
17
		break;
d6674d39   Nathanael Jourdane   Add error and inf...
18
	case 'getGranules':
50dd7220   Nathanael Jourdane   epntap.php works ...
19
		$response = getGranules();
68664dca   Nathanael Jourdane   make epntap php f...
20
		break;
d6674d39   Nathanael Jourdane   Add error and inf...
21
	default:
50dd7220   Nathanael Jourdane   epntap.php works ...
22
		$response = ['success' => false, 'msg' => 'Unknown action: ' . $action];
a8a12768   Nathanael Jourdane   Create the grid m...
23
		break;
8a0f1e9e   Nathanael Jourdane   Add autocompletio...
24
}
50dd7220   Nathanael Jourdane   epntap.php works ...
25
echo json_encode($response);
68664dca   Nathanael Jourdane   make epntap php f...
26

76142bdf   Nathanael Jourdane   epntap.php: Use o...
27
28
29
30
31
32
33
34
function getParams($paramNames, $default=null) {
    $params = [];
	foreach($paramNames as $paramName) {
        if(array_key_exists($paramName, $_GET)) {
            $params[$paramName] = filter_var($_GET[$paramName], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
        } else {
            $params[$paramName] = $default;
        }
5454dd64   Nathanael Jourdane   Refactoring epnta...
35
	}
76142bdf   Nathanael Jourdane   epntap.php: Use o...
36
	return $params;
5454dd64   Nathanael Jourdane   Refactoring epnta...
37
38
}

8c2fa14d   Nathanael Jourdane   Update services g...
39
40
function resolver() {
	$input = filter_var($_GET['input'], FILTER_SANITIZE_URL);
b5d477c6   Nathanael Jourdane   Allow multiple va...
41
42
43
44
45
	$words = preg_split("/ ?[;,] ?+/", $input);
	$lastWord = trim(array_pop($words));
	$firstsWords = implode(', ', $words);

	$resolver_url = "http://voparis-registry.obspm.fr/ssodnet/1/autocomplete?q=%22$lastWord%22";
68664dca   Nathanael Jourdane   make epntap php f...
46

50dd7220   Nathanael Jourdane   epntap.php works ...
47
	$response = ['success' => true, 'metaData' => ['root' => 'data', 'messageProperty' => 'msg']];
600add6e   Nathanael Jourdane   Display error if ...
48
49
	$content = file_get_contents($resolver_url);
	if($content) {
50dd7220   Nathanael Jourdane   epntap.php works ...
50
51
52
53
		$result = json_decode($content, true);
		$targets = array();
		foreach($result['hits'] as $e) {
			$aliases = '<li>' . join('</li><li>', $e['aliases']) . '</li>';
b5d477c6   Nathanael Jourdane   Allow multiple va...
54
55
			$text = (!empty($firstsWords) ? "$firstsWords, " : "") . $e['name'];
			$target = ['text' => $text, 'name' => $e['name'], 'type' => $e['type'], 'parent' => $e['parent'], 'aliases' => $aliases];
50dd7220   Nathanael Jourdane   epntap.php works ...
56
57
58
			array_push($targets, $target);
		}
		$response['data'] = $targets;
600add6e   Nathanael Jourdane   Display error if ...
59
	} else {
50dd7220   Nathanael Jourdane   epntap.php works ...
60
		$response['success'] = false;
600add6e   Nathanael Jourdane   Display error if ...
61
		$response['msg'] = "Resolver unreachable on $resolver_url.";
50dd7220   Nathanael Jourdane   epntap.php works ...
62
63
64
65
66
	}
	return $response;
}

function request($access_url, $query) {
853c8154   Nathanael Jourdane   Init start/stop d...
67
    error_log($query);
50dd7220   Nathanael Jourdane   epntap.php works ...
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
	$votMgr = new VOTableMgr;
	$params = 'FORMAT=votable&LANG=ADQL&REQUEST=doQuery';
	$url = $access_url . '/sync?' . $params . '&QUERY=' . urlencode(preg_replace('/\s+/', ' ', $query)); // remove also multiple whitespaces

	$votMgr->load($url);
	$data = $votMgr->parseStream();
	$error = $votMgr->getVotableError();

	$response = ['query' => $query, 'metaData' => ['root' => 'data', 'messageProperty' => 'msg']];
	if($error) {
		$response['success'] = false;
		$response['msg'] = $error;
	} else {
		$response['success'] = true;
		$response['data'] = $data;
	}
	return $response;
49401187   Nathanael Jourdane   epntap: Do not us...
85
86
87
88
89
90
}

/* Return the list of available services by querying some usual registries. */
function getServices() {
	$registriesURL = ["http://registry.euro-vo.org/regtap/tap", "http://dc.zah.uni-heidelberg.de/tap", "http://gavo.aip.de/tap", "http://reg.g-vo.org/tap"];
	$columns = ['short_name', 'res_title', 'ivoid', 'access_url', 'table_name', 'content_type', 'creator_seq', 'content_level', 'reference_url', 'created', 'updated'];
a8a12768   Nathanael Jourdane   Create the grid m...
91
	$query = "SELECT DISTINCT " . implode(', ', $columns) . " FROM rr.resource
49401187   Nathanael Jourdane   epntap: Do not us...
92
93
94
			NATURAL JOIN rr.res_schema NATURAL JOIN rr.res_table NATURAL JOIN rr.interface NATURAL JOIN rr.res_detail NATURAL JOIN rr.capability
			WHERE standard_id='ivo://ivoa.net/std/tap' AND intf_type='vs:paramhttp' AND detail_xpath='/capability/dataModel/@ivo-id'
			AND 1=ivo_nocasematch(detail_value, 'ivo://vopdc.obspm/std/EpnCore%') AND table_name LIKE '%.epn_core' ORDER BY short_name, table_name";
50dd7220   Nathanael Jourdane   epntap.php works ...
95
96

	$regNumber = 0;
853c8154   Nathanael Jourdane   Init start/stop d...
97
98
    $r = [];
    $lastErrorMessage = null;
50dd7220   Nathanael Jourdane   epntap.php works ...
99
	for(; $regNumber<count($registriesURL) ; $regNumber++) {
853c8154   Nathanael Jourdane   Init start/stop d...
100
101
		$r = request($registriesURL[$regNumber], $query);
		if($r['success']) {
50dd7220   Nathanael Jourdane   epntap.php works ...
102
			// Add several other parameters and remove AMDA
853c8154   Nathanael Jourdane   Init start/stop d...
103
104
105
106
107
108
			for($j=0 ; $j<count($r['data']) ; $j++) {
				$r['data'][$j]['id'] = generateServiceId($r['data'][$j]);
				$r['data'][$j]['nb_results'] = -1;
				$r['data'][$j]['info'] = 'Please make a query.';
				if($r['data'][$j]['id'] == 'cdpp/amda/amdadb') {
					array_splice($r['data'], $j, 1);
1813a0ba   Nathanael Jourdane   Remove AMDA to th...
109
110
					$j-=1;
				}
49401187   Nathanael Jourdane   epntap: Do not us...
111
			}
853c8154   Nathanael Jourdane   Init start/stop d...
112
113
			if(!is_null($lastErrorMessage)) {
				$r['msg'] = $lastErrorMessage;
173951f6   Nathanael Jourdane   Display the getSe...
114
			}
50dd7220   Nathanael Jourdane   epntap.php works ...
115
116
			break;
		} else {
853c8154   Nathanael Jourdane   Init start/stop d...
117
			$lastErrorMesage = 'Last tried registry (' . $registriesURL[$regNumber] . ') returned this error: ' . $r['msg'] . '.';
49401187   Nathanael Jourdane   epntap: Do not us...
118
		}
68664dca   Nathanael Jourdane   make epntap php f...
119
	}
853c8154   Nathanael Jourdane   Init start/stop d...
120
121
122
	
	if(!$r['success']) {
		$r['msg'] = 'Can not access any of these registries: ' . implode(', ', $registriesURL) . ', last error message is ' . $lastErrorMessage;
50dd7220   Nathanael Jourdane   epntap.php works ...
123
	}
853c8154   Nathanael Jourdane   Init start/stop d...
124
	return $r;
68664dca   Nathanael Jourdane   make epntap php f...
125
126
}

853c8154   Nathanael Jourdane   Init start/stop d...
127
function updateNbResults() {
76142bdf   Nathanael Jourdane   epntap.php: Use o...
128
    $p = getParams(['url', 'tableName', 'targetNames', 'productTypes', 'timeMin', 'timeMax']);
853c8154   Nathanael Jourdane   Init start/stop d...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
    $select = "SELECT COUNT(*) AS nb_res, min(time_min) as time_min, max(time_max) as time_max";
    $from = "FROM " . $p['tableName'];
    $where = createFilter($p['targetNames'], $p['productTypes'], $p['timeMin'], $p['timeMax']);
	$r = request($p['url'], "$select $from $where");
	if($r['success']) {
		$r['success'] = false;
		$r['msg'] = 'The service returned a bad value, can not get the number of results.';

		if(count($r['data']) < 1) {
			error_log('updateNbResults error: Too few returned rows.');
		} else if(count($r['data']) > 1) {
			error_log('updateNbResults error: Too many returned rows.');
		} else if(!array_key_exists(0, $r['data'])) {
			error_log('updateNbResults error: cant find raw item 0');

		} else if(is_null($r['data'][0])) {
			error_log('updateNbResults error: The returned raw is null.');
		} else if(!array_key_exists("nb_res", $r['data'][0])) {
            var_dump($r['data'][0]);
			error_log('updateNbResults error: cant find nb_res value in the row: ' . json_encode($r['data'][0]));
		} else if(!is_numeric($r['data'][0]['nb_res'])) {
			error_log('updateNbResults error: The returned value is not a number.');
50dd7220   Nathanael Jourdane   epntap.php works ...
151
		} else {
853c8154   Nathanael Jourdane   Init start/stop d...
152
153
154
155
156
157
158
			$r['success'] = true;
            $r['data'] = [
            	'nbRes' => (int)($r['data'][0]['nb_res']),
				'tMin' => JDToDate($r['data'][0]['time_min']),
				'tMax' => JDToDate($r['data'][0]['time_max'])
			];
			$r['msg'] = 'The service returned ' . ($r['data']['nbRes'] == 0 ? 'no' : $r['data']['nbRes']) . ' result' . ($r['data']['nbRes'] > 1 ? 's' : '') . ' for the given query.';
50dd7220   Nathanael Jourdane   epntap.php works ...
159
		}
8c2fa14d   Nathanael Jourdane   Update services g...
160
	}
853c8154   Nathanael Jourdane   Init start/stop d...
161
	return $r;
49401187   Nathanael Jourdane   epntap: Do not us...
162
163
}

d6674d39   Nathanael Jourdane   Add error and inf...
164
function getGranules() {
76142bdf   Nathanael Jourdane   epntap.php: Use o...
165
	$p = getParams(['url', 'tableName', 'sort', 'dir', 'targetNames', 'productTypes', 'timeMin', 'timeMax', 'start', 'limit', 'nbRes']);
853c8154   Nathanael Jourdane   Init start/stop d...
166
167
168
    $select = "SELECT TOP " . $p['limit'] .  " *";
    $from = "FROM " . $p['tableName'];
	$where = createFilter($p['targetNames'], $p['productTypes'], $p['timeMin'], $p['timeMax']);
50fc8d16   Nathanael Jourdane   bugfix #5846 epnt...
169
	$order = "ORDER BY " . (is_null($p['sort']) ? 'granule_uid ASC' : ($p['sort'] . ' ' . $p['dir']) . " OFFSET " . $p['start']);
853c8154   Nathanael Jourdane   Init start/stop d...
170
	$response = request($p['url'], "$select $from $where $order");
50dd7220   Nathanael Jourdane   epntap.php works ...
171
	if($response['success']) {
f82d19f1   Nathanael Jourdane   Display granules ...
172
173
174
175
176
		$visibleColumns = ['granule_gid', 'obs_id', 'dataproduct_type', 'time_min', 'time_max', 'instrument_name', 'processing_level', 'access_estsize', 'thumbnail_url', 'access_url']; // rest are hidden
		$names = ['granule_gid' => 'GID', 'dataproduct_type' => 'Type', 'processing_level' => 'Proc. lvl', 'access_estsize' => 'Size', 'access_url' => 'URL']; // default: pretty printed key name
		$renderers = ['dataproduct_type' => 'type', 'time_min' => 'date', 'time_max' => 'date', 'processing_level' => 'proc_lvl',
			'access_estsize' => 'size', 'thumbnail_url' => 'img', 'access_url' => 'link', 'access_format' => 'format']; // default: text
		$widths = ['obs_id' => 75, 'time_min' => 75, 'time_max' => 75, 'instrument_name' => 75, 'processing_level' => 60]; // default: 50
50dd7220   Nathanael Jourdane   epntap.php works ...
177
178
179
180

		$fields = array();
		$columns = array();
		foreach($response['data'][0] as $key => $value) {
50dd7220   Nathanael Jourdane   epntap.php works ...
181
182
183
184
			$fields[] = ['name' => $key, 'type' => 'string'];
			$columns[] = [
				'dataIndex' => $key,
				'text' => array_key_exists($key, $names) ? $names[$key] : ucfirst(str_replace('_', ' ', $key)),
f82d19f1   Nathanael Jourdane   Display granules ...
185
				'width' => array_key_exists($key, $widths) ? $widths[$key] : 50,
50dd7220   Nathanael Jourdane   epntap.php works ...
186
				'hidden' => !in_array($key, $visibleColumns),
a5475297   Nathanael Jourdane   use a hash for me...
187
188
				'filterable' => true,
				// 'filter' => ['type' => 'list', 'options' => ['Image', 'Map']],
465b7a40   Nathanael Jourdane   Escape quotes in ...
189
				'renderer' => 'granule.' . (array_key_exists($key, $renderers) ? $renderers[$key] : 'text')
50dd7220   Nathanael Jourdane   epntap.php works ...
190
191
			];
		}
a8a12768   Nathanael Jourdane   Create the grid m...
192

76142bdf   Nathanael Jourdane   epntap.php: Use o...
193
		$response['total'] = (int)$p['nbRes'];
50dd7220   Nathanael Jourdane   epntap.php works ...
194
195
		$response['metaData']['fields'] = $fields;
		$response['metaData']['columns'] = $columns;
a5475297   Nathanael Jourdane   use a hash for me...
196
		$response['metaData']['metaHash'] = md5(serialize($response['metaData']));
50dd7220   Nathanael Jourdane   epntap.php works ...
197
198
	}
	return $response;
d6674d39   Nathanael Jourdane   Add error and inf...
199
200
}

8c2fa14d   Nathanael Jourdane   Update services g...
201
202
// ----- utils -----

b5d477c6   Nathanael Jourdane   Allow multiple va...
203
function createFilter($targetNames, $productTypes, $timeMin, $timeMax) {
8c2fa14d   Nathanael Jourdane   Update services g...
204
	$filter = array();
053ffdb4   Nathanael Jourdane   bugFix targetName...
205
	if($targetNames) {
b5d477c6   Nathanael Jourdane   Allow multiple va...
206
		array_push($filter, "target_name IN ('" . join("', '", preg_split("/ ?[;,] ?+/", $targetNames)) . "')");
8c2fa14d   Nathanael Jourdane   Update services g...
207
208
209
210
211
	}
	if($productTypes) {
		array_push($filter, "dataproduct_type IN ('" . join("', '", explode(';', $productTypes)) . "')");
	}
	if($timeMin) {
e4785141   Nathanael Jourdane   Fix date filter i...
212
		array_push($filter, "time_max >= " . dateToJD($timeMin));
8c2fa14d   Nathanael Jourdane   Update services g...
213
214
	}
	if($timeMax) {
e4785141   Nathanael Jourdane   Fix date filter i...
215
		array_push($filter, "time_min <= " . dateToJD($timeMax));
8c2fa14d   Nathanael Jourdane   Update services g...
216
	}
853c8154   Nathanael Jourdane   Init start/stop d...
217
	return (count($filter) > 0 ? 'WHERE ' . join(' AND ', $filter) : '');
8c2fa14d   Nathanael Jourdane   Update services g...
218
219
220
221
222
223
224
225
226
227
228
}

/* Generate a unique service identifier from the service ivoid and the table name. */
function generateServiceId($service) {
	return str_replace(['ivo://', '.epn_core'], '', $service['ivoid'] . '/' . $service['table_name']);
}

function dateToJD($gregorian_date) {
	list($day, $month, $year, $hours, $minutes, $seconds) = preg_split('/[\s\/:]+/', $gregorian_date);
	return GregorianToJD($month, $day, $year) + $hours/24 + $minutes/(24*60) + $seconds/(24*60*60);
}
853c8154   Nathanael Jourdane   Init start/stop d...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244

function JDToDate($julianDay) {
    if(is_numeric($julianDay)) {
        $jd = floatval($julianDay);
        $t = fmod($jd - floor($jd) + 0.5, 1);
        $h = floor($t*24);
        $m = floor($t*24*60 - $h*60);
        $s = floor($t*24*60*60 - $h*60*60 - $m*60);
        $d = explode('/', jdtogregorian(floor($jd)));
        $date = sprintf("%02d", $d[1]) . '/' . sprintf("%02d", $d[0]) . '/' . sprintf("%02d", $d[2]);
        $time = sprintf("%02d", $h) . ':' . sprintf("%02d", $m) . ':' . sprintf("%02d", $s);
        return $date . ' ' . $time;
    } else {
        return '-';
    }
}