false, 'msg' => 'Unknown action: ' . $action]; break; } echo json_encode($response); 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; } } return $params; } function resolver() { $input = filter_var($_GET['input'], FILTER_SANITIZE_URL); $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"; $response = ['success' => true, 'metaData' => ['root' => 'data', 'messageProperty' => 'msg']]; $content = file_get_contents($resolver_url); if($content) { $result = json_decode($content, true); $targets = array(); foreach($result['hits'] as $e) { $aliases = '
  • ' . join('
  • ', $e['aliases']) . '
  • '; $text = (!empty($firstsWords) ? "$firstsWords, " : "") . $e['name']; $target = ['text' => $text, 'name' => $e['name'], 'type' => $e['type'], 'parent' => $e['parent'], 'aliases' => $aliases]; array_push($targets, $target); } $response['data'] = $targets; } else { $response['success'] = false; $response['msg'] = "Resolver unreachable on $resolver_url."; } return $response; } function request($access_url, $query) { # error_log($query); $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 if ($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; } /* Return the list of available services by querying some usual registries. */ function getServices() { $registriesURL = [ //"http://vao.stsci.edu/RegTAP/TapService.aspx", "http://voparis-rr.obspm.fr/tap", "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']; $query = "SELECT DISTINCT " . implode(', ', $columns) . " FROM rr.resource 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"; $regNumber = 0; $r = []; $lastErrorMessage = ''; for(; $regNumber < count($registriesURL) ; $regNumber++) { $r = request($registriesURL[$regNumber], $query); if($r['success']) { // Add several other parameters and remove AMDA for($j=0 ; $j 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.'); } else { $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.'; } } return $r; } function getGranules() { $p = getParams(['url', 'tableName', 'sort', 'dir', 'targetNames', 'productTypes', 'timeMin', 'timeMax', 'start', 'limit', 'nbRes']); $select = "SELECT TOP " . $p['limit'] . " *"; $from = "FROM " . $p['tableName']; $where = createFilter($p['targetNames'], $p['productTypes'], $p['timeMin'], $p['timeMax']); $order = "ORDER BY " . (is_null($p['sort']) ? 'granule_uid ASC' : ($p['sort'] . ' ' . $p['dir']) . " OFFSET " . $p['start']); $response = request($p['url'], "$select $from $where $order"); if($response['success']) { $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 $fields = array(); $columns = array(); foreach($response['data'][0] as $key => $value) { $fields[] = ['name' => $key, 'type' => 'string']; $columns[] = [ 'dataIndex' => $key, 'text' => array_key_exists($key, $names) ? $names[$key] : ucfirst(str_replace('_', ' ', $key)), 'width' => array_key_exists($key, $widths) ? $widths[$key] : 50, 'hidden' => !in_array($key, $visibleColumns), 'filterable' => true, // 'filter' => ['type' => 'list', 'options' => ['Image', 'Map']], 'renderer' => 'granule.' . (array_key_exists($key, $renderers) ? $renderers[$key] : 'text') ]; } $response['total'] = (int)$p['nbRes']; $response['metaData']['fields'] = $fields; $response['metaData']['columns'] = $columns; $response['metaData']['metaHash'] = md5(serialize($response['metaData'])); } return $response; } // ----- utils ----- function createFilter($targetNames, $productTypes, $timeMin, $timeMax) { $filter = array(); if($targetNames) { array_push($filter, "target_name IN ('" . join("', '", preg_split("/ ?[;,] ?+/", $targetNames)) . "')"); } if($productTypes) { array_push($filter, "dataproduct_type IN ('" . join("', '", explode(';', $productTypes)) . "')"); } if($timeMin) { array_push($filter, "time_max >= " . dateToJD($timeMin)); } if($timeMax) { array_push($filter, "time_min <= " . dateToJD($timeMax)); } return (count($filter) > 0 ? 'WHERE ' . join(' AND ', $filter) : ''); } /* 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); } 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 '-'; } }