diff --git a/deploy.json b/deploy.json
index 45b45883e..c2c798b56 100644
--- a/deploy.json
+++ b/deploy.json
@@ -65,11 +65,6 @@
"dst": "[[package]]/acquisition/cdcp/",
"match": "^.*\\.(py)$",
"add-header-comment": true
- },{
- "type": "move",
- "src": "src/acquisition/cdcp/cdc_upload.php",
- "dst": "[[auto_web]]/cdc_upload/index.php",
- "add-header-comment": true
},
"// acquisition - ght",
@@ -107,16 +102,6 @@
"dst": "[[package]]/acquisition/wiki/",
"match": "^.*\\.(py)$",
"add-header-comment": true
- },{
- "type": "move",
- "src": "src/acquisition/wiki/master.php",
- "dst": "[[auto_web]]/wiki/master.php",
- "add-header-comment": true
- },{
- "type": "move",
- "src": "src/acquisition/wiki/dashboard.php",
- "dst": "[[auto_web]]/wiki/index.php",
- "add-header-comment": true
},
"// acquisition - flusurv",
diff --git a/dev/docker/web/epidata/Dockerfile b/dev/docker/web/epidata/Dockerfile
deleted file mode 100644
index fa6d503a4..000000000
--- a/dev/docker/web/epidata/Dockerfile
+++ /dev/null
@@ -1,11 +0,0 @@
-# start with the `delphi_web` image
-FROM delphi_web
-
-# deploy the Epidata API (see `delphi-epidata/deploy.json`)
-COPY repos/delphi/delphi-epidata/src/server/*.html /var/www/html/epidata/
-COPY repos/delphi/delphi-epidata/src/server/*.php /var/www/html/epidata/
-
-# point to the development database (overwrites the production config)
-COPY repos/delphi/delphi-epidata/dev/docker/web/epidata/assets/database_config.php /var/www/html/epidata/
-
-RUN chmod o+r /var/www/html/epidata/*
diff --git a/dev/docker/web/epidata/README.md b/dev/docker/web/epidata/README.md
deleted file mode 100644
index 8656f3e66..000000000
--- a/dev/docker/web/epidata/README.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# `delphi_web_epidata`
-
-This image starts with Delphi's web server and adds the sources necessary for
-hosting the Epidata API.
-
-This image includes the file
-[`database_config.php`](assets/database_config.php), which points to a local
-container running the
-[`delphi_database_epidata` image](../../database/epidata/README.md).
-
-To start a container from this image, run:
-
-```bash
-docker run --rm -p 10080:80 \
- --network delphi-net --name delphi_web_epidata \
- delphi_web_epidata
-```
-
-You should be able to call the API by setting your base URL to
-`http://localhost:10080/epidata/api.php`. To verify that the container is alive
-and serving, visit in a web browser (or `curl`)
-http://localhost:10080/epidata/.
diff --git a/dev/docker/web/epidata/assets/database_config.php b/dev/docker/web/epidata/assets/database_config.php
deleted file mode 100644
index 7c7402f47..000000000
--- a/dev/docker/web/epidata/assets/database_config.php
+++ /dev/null
@@ -1,7 +0,0 @@
- 'delphi_database_epidata',
- 'port' => 3306,
-);
-?>
diff --git a/docs/epidata_development.md b/docs/epidata_development.md
index 44d13a348..a2f0b7e8e 100644
--- a/docs/epidata_development.md
+++ b/docs/epidata_development.md
@@ -116,7 +116,7 @@ above. The base images are built first, followed by the derived
`epidata`-specific images.
- The [`delphi_web_epidata` image](https://github.com/cmu-delphi/delphi-epidata/blob/main/dev/docker/web/epidata/README.md) adds
- the Epidata API to the `delphi_web` image.
+ the Epidata API to the `delphi_web_epidata` image.
- The
[`delphi_database_epidata` image](https://github.com/cmu-delphi/delphi-epidata/blob/main/dev/docker/database/epidata/README.md)
adds user accounts, `epidata` & other appropriate databases, and relevant tables
@@ -125,14 +125,8 @@ above. The base images are built first, followed by the derived
From the root of your workspace, all of the images can be built as follows:
```bash
-docker build -t delphi_web \
- -f repos/delphi/operations/dev/docker/web/Dockerfile .
-
-docker build -t delphi_web_epidata \
- -f repos/delphi/delphi-epidata/dev/docker/web/epidata/Dockerfile .
-
-docker build -t delphi_database \
- -f repos/delphi/operations/dev/docker/database/Dockerfile .
+docker build -t delphi_web_epidata\
+ -f ./devops/Dockerfile .;\
docker build -t delphi_database_epidata \
-f repos/delphi/delphi-epidata/dev/docker/database/epidata/Dockerfile .
@@ -394,33 +388,3 @@ The command above maps two local directories into the container:
- `/repos/delphi/delphi-epidata/src`: Just the source code, which forms the
container's `delphi.epidata` python package.
-### server code
-
-Local web sources (e.g. PHP files) can be bind-mounted into a
-`delphi_web_epidata` container as follows:
-
-```bash
-docker run --rm -p 127.0.0.1:10080:80 \
- --mount type=bind,source="$(pwd)"/repos/delphi/delphi-epidata/src/server/api.php,target=/var/www/html/epidata/api.php,readonly \
- --mount type=bind,source="$(pwd)"/repos/delphi/delphi-epidata/src/server/api_helpers.php,target=/var/www/html/epidata/api_helpers.php,readonly \
- --network delphi-net --name delphi_web_epidata \
- delphi_web_epidata
-```
-
-The command above mounts two specific files into the image. It may be tempting
-to bind mount the `src/server` directory rather than specific files, however
-that is currently problematic for a couple of reasons:
-
-1. `server/.htaccess` [from the local repository](https://github.com/cmu-delphi/delphi-epidata/blob/main/src/server/.htaccess) uses
- the `Header` directive. However, the webserver in the container doesn't have
- the corresponding module enabled. This causes the server to deny access to
- the API.
-2. `server/database_config.php`
- [in the image](https://github.com/cmu-delphi/delphi-epidata/blob/main/dev/docker/web/epidata/assets/database_config.php) contains
- database credentials for use in conjunction with the
- `delphi_database_epidata` container during development. However, the same
- file from [the local repository](https://github.com/cmu-delphi/delphi-epidata/blob/main/src/server/database_config.php) only
- contains placeholder values. This prevents communication with the database.
-
-There is currently no benefit to bind-mounting sources into the database
-container because schema changes require restarting the container anyway.
diff --git a/docs/new_endpoint_tutorial.md b/docs/new_endpoint_tutorial.md
index bd5634c9e..436b89908 100644
--- a/docs/new_endpoint_tutorial.md
+++ b/docs/new_endpoint_tutorial.md
@@ -273,10 +273,8 @@ already built the `delphi_python` image above:
```bash
# build web and database images for epidata
-docker build -t delphi_web \
- -f repos/delphi/operations/dev/docker/web/Dockerfile .
-docker build -t delphi_web_epidata \
- -f repos/delphi/delphi-epidata/dev/docker/web/epidata/Dockerfile .
+docker build -t delphi_web_epidata\
+ -f ./devops/Dockerfile .;\
docker build -t delphi_database_epidata \
-f repos/delphi/delphi-epidata/dev/docker/database/epidata/Dockerfile .
diff --git a/src/acquisition/cdcp/cdc_upload.php b/src/acquisition/cdcp/cdc_upload.php
deleted file mode 100644
index 3dfcb38f3..000000000
--- a/src/acquisition/cdcp/cdc_upload.php
+++ /dev/null
@@ -1,101 +0,0 @@
-
-
-
- CDC Page Stats
-
-
-
-
-
-
-
-
Upload Result
- 0) {
- printf('Error: upload failed (%d)', intval($_FILES['zip_file']['error']));
- } else if($fileType != 'zip') {
- printf('Error: expected *.zip, got *.%s', $fileType);
- } else {
- $template = 'openssl dgst -sha256 -hmac "%s" "%s" | cut -d " " -f 2';
- $command = sprintf($template, $hmacSecret, $_FILES['zip_file']['tmp_name']);
- $hmac = trim(shell_exec($command));
- // todo - constant time comparison
- if($hmac === $_REQUEST['hmac']) {
- $target_dir = '/common/cdc_stage/';
- $target_file = $target_dir . time() . '_' . $fileName;
- if (move_uploaded_file($_FILES['zip_file']['tmp_name'], $target_file)) {
- mysql_query('CALL automation.RunStep(46)'); // Process CDCP Data
- printf('Success, thanks!');
- } else {
- printf('Error: something is wrong with file permissions.');
- }
- } else {
- $expected = substr($hmac, 0, 8) . '...';
- printf("Error: HMAC mismatch, expected [{$expected}].");
- sleep(5);
- }
- }
- } else {
- ?>
-
Upload zip file
-
-
- (We have data through = $d ?>.)
-
-
-
-
-
- To compute the hmac of your file, run [ openssl dgst -sha256 -hmac "<secret>" "<filename>" ]. The hmac should be a 64 character string of hex digits (32 bytes, 256 bits).
-
-
-
-
diff --git a/src/acquisition/wiki/dashboard.php b/src/acquisition/wiki/dashboard.php
deleted file mode 100644
index 09ae0e9d8..000000000
--- a/src/acquisition/wiki/dashboard.php
+++ /dev/null
@@ -1,182 +0,0 @@
-
-
-
-
-
- Wiki Status
-
-
-
-
-
- Workers
-
- Worker | Download (GB) | Num Jobs | Last Job Finished (sec) |
- = date_sub(now(), interval 1 hour) order by max(datetime)");
- $num = 0;
- while($row = mysql_fetch_array($result)) {
- printf("{$row['worker']} | %.1f | {$row['jobs']} | {$row['seen']} |
", floatval($row['dl']));
- $num++;
- }
- ?>
-
-
- Jobs
-
- Status | Num Jobs | Description |
- {$row['status']} | {$row['num']} | {$desc} | ");
- }
- ?>
-
-
- 0) {
- print(" curr");
- }
- print("\">");
- $st_1 = intval($row['st_1']);
- $st0 = intval($row['st0']);
- $st1 = intval($row['st1']);
- $st2 = intval($row['st2']);
- $st3 = intval($row['st3']);
- $total = $st_1 + $st0 + $st1 + $st2 + $st3;
- if($st3 == $total) {
- print("");
- } else {
- printf("", (100 * $st_1 / $total));
- printf("", (100 * $st0 / $total));
- printf("", (100 * $st1 / $total));
- printf("", (100 * $st2 / $total));
- printf("", (100 * $st3 / $total));
- }
- print("");
- }
- ?>
-
-
diff --git a/src/acquisition/wiki/master.php b/src/acquisition/wiki/master.php
deleted file mode 100644
index 99ace0cd4..000000000
--- a/src/acquisition/wiki/master.php
+++ /dev/null
@@ -1,53 +0,0 @@
-{'size'}), mysql_real_escape_string($obj->{'worker'}), floatval($obj->{'elapsed'}), mysql_real_escape_string($obj->{'data'}), intval($obj->{'id'})));
- echo 'ok';
- } else {
- sleep(5);
- http_response_code(400);
- echo 'wrong hmac';
- }
-} else {
- http_response_code(400);
- echo 'bad request';
-}
-?>
diff --git a/src/server/api.php b/src/server/api.php
deleted file mode 100644
index 404bd80c2..000000000
--- a/src/server/api.php
+++ /dev/null
@@ -1,2232 +0,0 @@
- Secrets::$api['twitter'],
- 'ght' => Secrets::$api['ght'],
- 'fluview' => Secrets::$api['fluview'],
- 'cdc' => Secrets::$api['cdc'],
- 'sensors' => Secrets::$api['sensors'],
- 'sensor_subsets' => Secrets::$api['sensor_subsets'],
- 'quidel' => Secrets::$api['quidel'],
- 'norostat' => Secrets::$api['norostat'],
- 'afhsb' => Secrets::$api['afhsb']
-);
-// begin sensor query authentication configuration
-// A multimap of sensor names to the "granular" auth tokens that can be used to access them; excludes the "global" sensor auth key that works for all sensors:
-$GRANULAR_SENSOR_AUTH_TOKENS = array(
- 'twtr' => array($AUTH['sensor_subsets']['twtr_sensor']),
- 'gft' => array($AUTH['sensor_subsets']['gft_sensor']),
- 'ght' => array($AUTH['sensor_subsets']['ght_sensors']),
- 'ghtj' => array($AUTH['sensor_subsets']['ght_sensors']),
- 'cdc' => array($AUTH['sensor_subsets']['cdc_sensor']),
- 'quid' => array($AUTH['sensor_subsets']['quid_sensor']),
- 'wiki' => array($AUTH['sensor_subsets']['wiki_sensor']),
-);
-// A set of sensors that do not require an auth key to access:
-$OPEN_SENSORS = array(
- 'sar3',
- 'epic',
- 'arch',
-);
-// Limits on the number of effective auth token equality checks performed per sensor query; generate auth tokens with appropriate levels of entropy according to the limits below:
-$MAX_GLOBAL_AUTH_CHECKS_PER_SENSOR_QUERY = 1; // (but imagine is larger to futureproof)
-$MAX_GRANULAR_AUTH_CHECKS_PER_SENSOR_QUERY = 30; // (but imagine is larger to futureproof)
-// A (currently redundant) limit on the number of auth tokens that can be provided:
-$MAX_AUTH_KEYS_PROVIDED_PER_SENSOR_QUERY = 1;
-// end sensor query authentication configuration
-
-// result limit, ~10 years of daily data
-$MAX_RESULTS = 3650;
-
-// queries the `fluview` and `fluview_imputed` tables
-// $epiweeks (required): array of epiweek values/ranges
-// $regions (required): array of region names
-// $issues (optional): array of epiweek values/ranges
-// overrides $lag
-// default: most recent issue
-// $lag (optional): number of weeks between each epiweek and its issue
-// overridden by $issues
-// default: most recent issue
-// $authorized: determines whether private data (i.e. `fluview_imputed`) is
-// included in the result
-function get_fluview($epiweeks, $regions, $issues, $lag, $authorized) {
- $epidata = array();
- // public data
- $table = '`fluview` fv';
- $fields = "fv.`release_date`, fv.`issue`, fv.`epiweek`, fv.`region`, fv.`lag`, fv.`num_ili`, fv.`num_patients`, fv.`num_providers`, fv.`wili`, fv.`ili`, fv.`num_age_0`, fv.`num_age_1`, fv.`num_age_2`, fv.`num_age_3`, fv.`num_age_4`, fv.`num_age_5`";
- _get_fluview_by_table($epidata, $epiweeks, $regions, $issues, $lag, $table, $fields);
- if(!$authorized) {
- // Make a special exception for New York. It is a (weighted) sum of two
- // constituent locations -- "ny_minus_jfk" and "jfk" -- both of which are
- // publicly available.
- if(in_array('ny', array_map('strtolower', $regions))) {
- $regions = array('ny');
- $authorized = true;
- }
- }
- if($authorized) {
- // private data (no release date, no age groups, and wili is equal to ili)
- $table = '`fluview_imputed` fv';
- $fields = "NULL `release_date`, fv.`issue`, fv.`epiweek`, fv.`region`, fv.`lag`, fv.`num_ili`, fv.`num_patients`, fv.`num_providers`, fv.`ili` `wili`, fv.`ili`, NULL `num_age_0`, NULL `num_age_1`, NULL `num_age_2`, NULL `num_age_3`, NULL `num_age_4`, NULL `num_age_5`";
- _get_fluview_by_table($epidata, $epiweeks, $regions, $issues, $lag, $table, $fields);
- }
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// a helper function to query `fluview` and `fluview_imputed` individually
-// parameters
-function _get_fluview_by_table(&$epidata, $epiweeks, $regions, $issues, $lag, $table, $fields) {
- // basic query info
- $order = "fv.`epiweek` ASC, fv.`region` ASC, fv.`issue` ASC";
- // build the epiweek filter
- $condition_epiweek = filter_integers('fv.`epiweek`', $epiweeks);
- // build the region filter
- $condition_region = filter_strings('fv.`region`', $regions);
- if($issues !== null) {
- // build the issue filter
- $condition_issue = filter_integers('fv.`issue`', $issues);
- // final query using specific issues
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) AND ({$condition_issue}) ORDER BY {$order}";
- } else if($lag !== null) {
- // build the lag filter
- $condition_lag = "(fv.`lag` = {$lag})";
- // final query using lagged issues
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) AND ({$condition_lag}) ORDER BY {$order}";
- } else {
- // final query using most recent issues
- $subquery = "(SELECT max(`issue`) `max_issue`, `epiweek`, `region` FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) GROUP BY `epiweek`, `region`) x";
- $condition = "x.`max_issue` = fv.`issue` AND x.`epiweek` = fv.`epiweek` AND x.`region` = fv.`region`";
- $query = "SELECT {$fields} FROM {$table} JOIN {$subquery} ON {$condition} ORDER BY {$order}";
- }
- // get the data from the database
- $fields_string = array('release_date', 'region');
- $fields_int = array('issue', 'epiweek', 'lag', 'num_ili', 'num_patients', 'num_providers', 'num_age_0', 'num_age_1', 'num_age_2', 'num_age_3', 'num_age_4', 'num_age_5');
- $fields_float = array('wili', 'ili');
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
-}
-
-// queries the `fluview_clinical` table
-// $epiweeks (required): array of epiweek values/ranges
-// $regions (required): array of region names
-// $issues (optional): array of epiweek values/ranges
-// overrides $lag
-// default: most recent issue
-// $lag (optional): number of weeks between each epiweek and its issue
-// overridden by $issues
-// default: most recent issue
-function get_fluview_clinical($epiweeks, $regions, $issues, $lag) {
- // store the results in an array
- $epidata = array();
- // set up for query
- $table = "`fluview_clinical` fvc";
- // $fields = 'fvc.`release_date`, fvc.`issue`, fvc.`epiweek`, fvc.`region`, fvc.`lag`, fvc.`total_specimens`, fvc.`total_a_h1n1`, fvc.`total_a_h3`, fvc.`total_a_h3n2v`, fvc.`total_a_no_sub`, fvc.`total_b`, fvc.`total_b_vic`, fvc.`total_b_yam`';
- $fields = "fvc.`release_date`, fvc.`issue`, fvc.`epiweek`, fvc.`region`, fvc.`lag`, fvc.`total_specimens`, fvc.`total_a`, fvc.`total_b`, fvc.`percent_positive`, fvc.`percent_a`, fvc.`percent_b`";
- $order = "fvc.`epiweek` ASC, fvc.`region` ASC, fvc.`issue` ASC";
- // create conditions
- $condition_epiweek = filter_integers("fvc.`epiweek`", $epiweeks);
- $condition_region = filter_strings("fvc.`region`", $regions);
- if ($issues !== null) {
- // using specific issues
- $condition_issue = filter_integers("fvc.`issue`", $issues);
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) AND ({$condition_issue}) ORDER BY {$order}";
- } else if ($lag !== null) {
- // using lagged issues
- $condition_lag = '(fvc.`lag` = {$lag})';
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) AND ({$condition_lag}) ORDER BY {$order}";
- } else {
- // using most recent issues
- $subquery = "(SELECT max(`issue`) `max_issue`, `epiweek`, `region` FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) GROUP BY `epiweek`, `region`) x";
- $condition = "x.`max_issue` = fvc.`issue` AND x.`epiweek` = fvc.`epiweek` AND x.`region` = fvc.`region`";
- $query = "SELECT {$fields} FROM {$table} JOIN {$subquery} ON {$condition} ORDER BY {$order}";
- }
- // get the data from the database
- $fields_string = array('release_date', 'region');
- $fields_float = array('percent_positive', 'percent_a', 'percent_b');
- $fields_int = array('issue', 'epiweek', 'lag', 'total_specimens', 'total_a', 'total_b');
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the result, if any
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `flusurv` table
-// $epiweeks (required): array of epiweek values/ranges
-// $locations (required): array of locations names
-// $issues (optional): array of epiweek values/ranges
-// overrides $lag
-// default: most recent issue
-// $lag (optional): number of weeks between each epiweek and its issue
-// overridden by $issues
-// default: most recent issue
-function get_flusurv($epiweeks, $locations, $issues, $lag) {
- // basic query info
- $table = '`flusurv` fs';
- $fields = "fs.`release_date`, fs.`issue`, fs.`epiweek`, fs.`location`, fs.`lag`, fs.`rate_age_0`, fs.`rate_age_1`, fs.`rate_age_2`, fs.`rate_age_3`, fs.`rate_age_4`, fs.`rate_overall`";
- $order = "fs.`epiweek` ASC, fs.`location` ASC, fs.`issue` ASC";
- // build the epiweek filter
- $condition_epiweek = filter_integers('fs.`epiweek`', $epiweeks);
- // build the location filter
- $condition_location = filter_strings('fs.`location`', $locations);
- if($issues !== null) {
- // build the issue filter
- $condition_issue = filter_integers('fs.`issue`', $issues);
- // final query using specific issues
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_location}) AND ({$condition_issue}) ORDER BY {$order}";
- } else if($lag !== null) {
- // build the lag filter
- $condition_lag = "(fs.`lag` = {$lag})";
- // final query using lagged issues
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_location}) AND ({$condition_lag}) ORDER BY {$order}";
- } else {
- // final query using most recent issues
- $subquery = "(SELECT max(`issue`) `max_issue`, `epiweek`, `location` FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_location}) GROUP BY `epiweek`, `location`) x";
- $condition = "x.`max_issue` = fs.`issue` AND x.`epiweek` = fs.`epiweek` AND x.`location` = fs.`location`";
- $query = "SELECT {$fields} FROM {$table} JOIN {$subquery} ON {$condition} ORDER BY {$order}";
- }
- // get the data from the database
- $epidata = array();
- $fields_string = array('release_date', 'location');
- $fields_int = array('issue', 'epiweek', 'lag');
- $fields_float = array('rate_age_0', 'rate_age_1', 'rate_age_2', 'rate_age_3', 'rate_age_4', 'rate_overall');
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `paho_dengue` table
-// $epiweeks (required): array of epiweek values/ranges
-// $regions (required): array of region names
-// $issues (optional): array of epiweek values/ranges
-// overrides $lag
-// default: most recent issue
-// $lag (optional): number of weeks between each epiweek and its issue
-// overridden by $issues
-// default: most recent issue
-function get_paho_dengue($epiweeks, $regions, $issues, $lag) {
- // store the results in an array
- $epidata = array();
- // set up for query
- $table = "`paho_dengue` pd";
- $fields = "pd.`release_date`, pd.`issue`, pd.`epiweek`, pd.`region`, pd.`lag`, pd.`total_pop`, pd.`serotype`, pd.`num_dengue`, pd.`incidence_rate`, pd.`num_severe`, pd.`num_deaths`";
- $order = "pd.`epiweek` ASC, pd.`region` ASC, pd.`issue` ASC";
- // create conditions
- $condition_epiweek = filter_integers("pd.`epiweek`", $epiweeks);
- $condition_region = filter_strings("pd.`region`", $regions);
- if ($issues !== null) {
- // using specific issues
- $condition_issue = filter_integers("pd.`issue`", $issues);
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) AND ({$condition_issue}) ORDER BY {$order}";
- } else if ($lag !== null) {
- // using lagged issues
- $condition_lag = '(pd.`lag` = {$lag})';
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) AND ({$condition_lag}) ORDER BY {$order}";
- } else {
- // using most recent issues
- $subquery = "(SELECT max(`issue`) `max_issue`, `epiweek`, `region` FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) GROUP BY `epiweek`, `region`) x";
- $condition = "x.`max_issue` = pd.`issue` AND x.`epiweek` = pd.`epiweek` AND x.`region` = pd.`region`";
- $query = "SELECT {$fields} FROM {$table} JOIN {$subquery} ON {$condition} ORDER BY {$order}";
- }
- // get the data from the database
- $fields_string = array('release_date', 'region', 'serotype');
- $fields_float = array('incidence_rate');
- $fields_int = array('issue', 'epiweek', 'lag', 'total_pop', 'num_dengue', 'num_severe', 'num_deaths');
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the result, if any
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `ecdc_ili` table
-// $epiweeks (required): array of epiweek values/ranges
-// $regions (required): array of region names
-// $issues (optional): array of epiweek values/ranges
-// overrides $lag
-// default: most recent issue
-// $lag (optional): number of weeks between each epiweek and its issue
-// overridden by $issues
-// default: most recent issue
-function get_ecdc_ili($epiweeks, $regions, $issues, $lag) {
- // store the results in an array
- $epidata = array();
- // set up for query
- $table = "`ecdc_ili` ec";
- $fields = "ec.`release_date`, ec.`issue`, ec.`epiweek`, ec.`region`, ec.`lag`, ec.`incidence_rate`";
- $order = "ec.`epiweek` ASC, ec.`region` ASC, ec.`issue` ASC";
- // create conditions
- $condition_epiweek = filter_integers("ec.`epiweek`", $epiweeks);
- $condition_region = filter_strings("ec.`region`", $regions);
- if ($issues !== null) {
- // using specific issues
- $condition_issue = filter_integers("ec.`issue`", $issues);
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) AND ({$condition_issue}) ORDER BY {$order}";
- } else if ($lag !== null) {
- // using lagged issues
- $condition_lag = '(ec.`lag` = {$lag})';
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) AND ({$condition_lag}) ORDER BY {$order}";
- } else {
- // using most recent issues
- $subquery = "(SELECT max(`issue`) `max_issue`, `epiweek`, `region` FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) GROUP BY `epiweek`, `region`) x";
- $condition = "x.`max_issue` = ec.`issue` AND x.`epiweek` = ec.`epiweek` AND x.`region` = ec.`region`";
- $query = "SELECT {$fields} FROM {$table} JOIN {$subquery} ON {$condition} ORDER BY {$order}";
- }
- // get the data from the database
- $fields_string = array('release_date', 'region');
- $fields_float = array('incidence_rate');
- $fields_int = array('issue', 'epiweek', 'lag');
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the result, if any
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `kcdc_ili` table
-// $epiweeks (required): array of epiweek values/ranges
-// $regions (required): array of region names
-// $issues (optional): array of epiweek values/ranges
-// overrides $lag
-// default: most recent issue
-// $lag (optional): number of weeks between each epiweek and its issue
-// overridden by $issues
-// default: most recent issue
-function get_kcdc_ili($epiweeks, $regions, $issues, $lag) {
- // store the results in an array
- $epidata = array();
- // set up for query
- $table = "`kcdc_ili` kc";
- $fields = "kc.`release_date`, kc.`issue`, kc.`epiweek`, kc.`region`, kc.`lag`, kc.`ili`";
- $order = "kc.`epiweek` ASC, kc.`region` ASC, kc.`issue` ASC";
- // create conditions
- $condition_epiweek = filter_integers("kc.`epiweek`", $epiweeks);
- $condition_region = filter_strings("kc.`region`", $regions);
- if ($issues !== null) {
- // using specific issues
- $condition_issue = filter_integers("kc.`issue`", $issues);
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) AND ({$condition_issue}) ORDER BY {$order}";
- } else if ($lag !== null) {
- // using lagged issues
- $condition_lag = '(kc.`lag` = {$lag})';
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) AND ({$condition_lag}) ORDER BY {$order}";
- } else {
- // using most recent issues
- $subquery = "(SELECT max(`issue`) `max_issue`, `epiweek`, `region` FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) GROUP BY `epiweek`, `region`) x";
- $condition = "x.`max_issue` = kc.`issue` AND x.`epiweek` = kc.`epiweek` AND x.`region` = kc.`region`";
- $query = "SELECT {$fields} FROM {$table} JOIN {$subquery} ON {$condition} ORDER BY {$order}";
- }
- // get the data from the database
- $fields_string = array('release_date', 'region');
- $fields_float = array('ili');
- $fields_int = array('issue', 'epiweek', 'lag');
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the result, if any
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `gft` table
-// $epiweeks (required): array of epiweek values/ranges
-// $locations (required): array of location names
-function get_gft($epiweeks, $locations) {
- // basic query info
- $table = '`gft` g';
- $fields = "g.`epiweek`, g.`location`, g.`num`";
- $order = "g.`epiweek` ASC, g.`location` ASC";
- // build the epiweek filter
- $condition_epiweek = filter_integers('g.`epiweek`', $epiweeks);
- // build the location filter
- $condition_location = filter_strings('g.`location`', $locations);
- // final query using specific issues
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_location}) ORDER BY {$order}";
- // get the data from the database
- $epidata = array();
- execute_query($query, $epidata, array('location'), array('epiweek', 'num'), null);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `ght` table
-// $epiweeks (required): array of epiweek values/ranges
-// $locations (required): array of location names
-// $query (required): search query or topic ID
-function get_ght($epiweeks, $locations, $query) {
- // basic query info
- $table = '`ght` g';
- $fields = "g.`epiweek`, g.`location`, g.`value`";
- $order = "g.`epiweek` ASC, g.`location` ASC";
- // build the epiweek filter
- $condition_epiweek = filter_integers('g.`epiweek`', $epiweeks);
- // build the location filter
- $condition_location = filter_strings('g.`location`', $locations);
- // build the query filter
- $condition_query = filter_strings('g.`query`', array($query));
- // final query using specific issues
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_location}) AND ({$condition_query}) ORDER BY {$order}";
- // get the data from the database
- $epidata = array();
- execute_query($query, $epidata, array('location'), array('epiweek'), array('value'));
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `twitter` table
-// $locations (required): array of location names
-// $dates (required): array of date or epiweek values/ranges
-// $resolution (required): either 'daily' or 'weekly'
-function get_twitter($locations, $dates, $resolution) {
- global $dbh;
- // basic query info
- $table = '`twitter` t';
- // build the date filter and set field names
- $fields_string = array('location');
- $fields_int = array('num', 'total');
- $fields_float = array('percent');
- if($resolution === 'daily') {
- $date_field = 't.`date`';
- $date_name = 'date';
- $condition_date = filter_dates($date_field, $dates);
- array_push($fields_string, $date_name);
- } else {
- $date_field = 'yearweek(t.`date`, 6)';
- $date_name = 'epiweek';
- $condition_date = filter_integers($date_field, $dates);
- array_push($fields_int, $date_name);
- }
- $fields = "{$date_field} `{$date_name}`, sum(t.`num`) `num`, sum(t.`total`) `total`, round(100 * sum(t.`num`) / sum(t.`total`), 8) `percent`";
- // for consistency (some rows have low `total`, or `num` > `total`), filter out 2% of rows with highest `percent`
- $condition_filter = 't.`num` / t.`total` <= 0.019';
- // split locations into national/regional/state
- $regions = array();
- $states = array();
- foreach($locations as $location) {
- $location = strtolower($location);
- if(in_array($location, array('nat', 'hhs1', 'hhs2', 'hhs3', 'hhs4', 'hhs5', 'hhs6', 'hhs7', 'hhs8', 'hhs9', 'hhs10', 'cen1', 'cen2', 'cen3', 'cen4', 'cen5', 'cen6', 'cen7', 'cen8', 'cen9'))) {
- array_push($regions, $location);
- } else {
- array_push($states, $location);
- }
- }
- // initialize the epidata array
- $epidata = array();
- // query each region type individually (the data is stored by state, so getting regional data requires some extra processing)
- foreach($regions as $region) {
- $region = mysqli_real_escape_string($dbh, $region);
- if($region === 'nat') {
- // final query for U.S. National
- $query = "SELECT {$fields}, '{$region}' `location` FROM {$table} WHERE ({$condition_filter}) AND ({$condition_date}) GROUP BY {$date_field} ORDER BY {$date_field} ASC";
- } else {
- // build the location filter
- $condition_location = "`state` IN (" . get_region_states($region) . ")";
- // final query for HHS Regions
- $query = "SELECT {$fields}, '{$region}' `location` FROM {$table} WHERE ({$condition_filter}) AND ({$condition_date}) AND ({$condition_location}) GROUP BY {$date_field} ORDER BY {$date_field} ASC";
- }
- // append query results to the epidata array
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- }
- // query all states together
- if(count($states) !== 0) {
- // build the location filter
- $condition_location = filter_strings('t.`state`', $states);
- // final query for states
- $query = "SELECT {$fields}, t.`state` `location` FROM {$table} WHERE ({$condition_filter}) AND ({$condition_date}) AND ({$condition_location}) GROUP BY {$date_field}, t.`state` ORDER BY {$date_field} ASC, t.`state` ASC";
- // append query results to the epidata array
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- }
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `wiki` table
-// $articles (required): array of article titles
-// $language (required): specify the language of articles we want to retrieve
-// $dates (required): array of date or epiweek values/ranges
-// $resolution (required): either 'daily' or 'weekly'
-// $hours (optional): array of hour values/ranges
-// if present, $hours determines which counts are used within each day; otherwise all counts are used
-// for example, if hours=[4], then only the 4 AM (UTC) stream is returned
-function get_wiki($articles, $language, $dates, $resolution, $hours) {
- // required for `mysqli_real_escape_string`
- global $dbh;
- $language = mysqli_real_escape_string($dbh, $language);
- // basic query info
- // in a few rare instances (~6 total), `total` is unreasonably high; something glitched somewhere, just ignore it
- // $table = '`wiki` w JOIN (SELECT * FROM `wiki_meta` WHERE `total` < 100000000) m ON m.`datetime` = w.`datetime`';
- // We select rows by language and then the problem is converted to the original one, and the rest of code can be same
- $table = "( SELECT * FROM `wiki` WHERE `language` = '$language' ) w JOIN (SELECT * FROM `wiki_meta` WHERE `total` < 100000000 AND `language` = '$language' ) m ON m.`datetime` = w.`datetime`";
- // build the date filter and set field names
- $fields_string = array('article');
- $fields_int = array('count', 'total', 'hour');
- $fields_float = array('value');
- if($resolution === 'daily') {
- $date_field = 'm.`date`';
- $date_name = 'date';
- $condition_date = filter_dates($date_field, $dates);
- array_push($fields_string, $date_name);
- } else {
- $date_field = 'm.`epiweek`';
- $date_name = 'epiweek';
- $condition_date = filter_integers($date_field, $dates);
- array_push($fields_int, $date_name);
- }
- $fields = "{$date_field} `{$date_name}`, w.`article`, sum(w.`count`) `count`, sum(m.`total`) `total`, round(sum(w.`count`) / (sum(m.`total`) * 1e-6), 8) `value`";
- // build the article filter
- $condition_article = filter_strings('w.`article`', $articles);
- if($hours !== null) {
- // filter by specific hours
- $condition_hour = filter_integers('hour(m.`datetime`)', $hours);
- // final query, only taking counts from specific hours of the day
- $query = "SELECT {$fields}, hour(m.`datetime`) `hour` FROM {$table} WHERE ({$condition_date}) AND ({$condition_article}) AND ({$condition_hour}) GROUP BY {$date_field}, w.`article`, hour(m.`datetime`) ORDER BY {$date_field} ASC, w.`article` ASC, hour(m.`datetime`) ASC";
- } else {
- // final query, summing over all hours of the day
- $query = "SELECT {$fields}, -1 `hour` FROM {$table} WHERE ({$condition_date}) AND ({$condition_article}) GROUP BY {$date_field}, w.`article` ORDER BY {$date_field} ASC, w.`article` ASC";
- }
- // get the data from the database
- $epidata = array();
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `quidel` table
-// $locations (required): array of location names
-// $epiweeks (required): array of epiweek values/ranges
-function get_quidel($locations, $epiweeks) {
- // basic query info
- $table = '`quidel` q';
- $fields = "q.`location`, q.`epiweek`, q.`value`";
- $order = "q.`epiweek` ASC, q.`location` ASC";
- // data type of each field
- $fields_string = array('location');
- $fields_int = array('epiweek');
- $fields_float = array('value');
- // build the location filter
- $condition_location = filter_strings('q.`location`', $locations);
- // build the epiweek filter
- $condition_epiweek = filter_integers('q.`epiweek`', $epiweeks);
- // the query
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_location}) AND ({$condition_epiweek}) ORDER BY {$order}";
- // get the data from the database
- $epidata = array();
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `norostat_point` table
-// $locations (required): single location value (str listing included states)
-// $epiweeks (required): array of epiweek values/ranges
-function get_norostat($location, $epiweeks) {
- // todo add release/issue args
- //
- // build the filters:
- $condition_location = filter_strings('`norostat_raw_datatable_location_pool`.`location`', [$location]);
- $condition_epiweek = filter_integers('`latest`.`epiweek`', $epiweeks);
- // get the data from the database
- $epidata = array();
- // (exclude "location" from output to reduce size & ugliness of result,
- // transfer bandwidth required; it would just be a repeated echo of the input
- // $location)
- $fields_string = array('release_date');
- $fields_int = array('epiweek', 'value');
- $query = "
- SELECT `latest`.`release_date`, `latest`.`epiweek`, `latest`.`new_value` AS `value`
- FROM `norostat_point_diffs` AS `latest`
- LEFT JOIN `norostat_raw_datatable_location_pool` USING (`location_id`)
- LEFT JOIN (
- SELECT * FROM `norostat_point_diffs`
- ) `later`
- ON `latest`.`location_id` = `later`.`location_id` AND
- `latest`.`epiweek` = `later`.`epiweek` AND
- (`latest`.`release_date`, `latest`.`parse_time`) <
- (`later`.`release_date`, `later`.`parse_time`) AND
- `later`.`new_value` IS NOT NULL
- WHERE ({$condition_location}) AND
- ({$condition_epiweek}) AND
- `later`.`parse_time` IS NULL AND
- `latest`.`new_value` IS NOT NULL
- ";
- // xxx may reorder epiweeks
- execute_query($query, $epidata, $fields_string, $fields_int, null);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `afhsb_00to13` table
-// $epiweeks (required): array of epiweek values/ranges
-// $locations (required): array of location names
-// $flu_types (required): array of flu types
-function get_afhsb($locations, $epiweeks, $flu_types) {
- global $dbh;
- $epidata = array();
- // split locations into national/regional/state
- $location_dict = array("hhs" => array(), "cen" => array(),
- "state" => array(), "country" => array());
- foreach($locations as $location) {
- $location = strtolower($location);
- if(substr($location, 0, 3) === "hhs") {
- array_push($location_dict["hhs"], $location);
- } elseif (substr($location, 0, 3) === "cen") {
- array_push($location_dict["cen"], $location);
- } elseif (strlen($location) === 3) {
- array_push($location_dict["country"], $location);
- } elseif (strlen($location) === 2) {
- array_push($location_dict["state"], $location);
- }
- }
- // split flu types into disjoint/subset
- $disjoint_flus = array();
- $subset_flus = array();
- foreach($flu_types as $flu_type) {
- if(in_array($flu_type, array('flu1','flu2-flu1','flu3-flu2','ili-flu3'))) {
- array_push($disjoint_flus, $flu_type);
- } elseif(in_array($flu_type, array('flu2','flu3','ili'))) {
- array_push($subset_flus, $flu_type);
- }
- }
- foreach($location_dict as $location_type=>$locs) {
- if(!empty($locs)) {
- _get_afhsb_by_table($epidata, $location_type, $epiweeks, $locs, $disjoint_flus, $subset_flus);
- }
- }
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// A helper function to query afhsb tables
-function _get_afhsb_by_table(&$epidata, $location_type, $epiweeks, $locations, $disjoint_flus, $subset_flus) {
- // basic query info
- $table = (in_array($location_type, array("hhs", "cen"))) ? "afhsb_00to13_region" : "afhsb_00to13_state";
- $fields = "`epiweek`, `{$location_type}` `location`, sum(`visit_sum`) `visit_sum`";
- $group = '`epiweek`, `location`';
- $order = "`epiweek` ASC, `location` ASC";
- $fields_string = array('location', 'flu_type');
- $fields_int = array('epiweek', 'visit_sum');
- // build the epiweek filter
- $condition_epiweek = filter_integers('`epiweek`', $epiweeks);
- // build the location filter
- $condition_location = filter_strings($location_type, $locations);
-
- // subset flu types: flu2, flu3, ili
- $flu_mapping = array('flu2' => array('flu1','flu2-flu1'),
- 'flu3' => array('flu1','flu2-flu1','flu3-flu2'),
- 'ili' => array('flu1','flu2-flu1','flu3-flu2','ili-flu3'));
- foreach($subset_flus as $subset_flu) {
- $condition_flu = filter_strings('`flu_type`', $flu_mapping[$subset_flu]);
- $query = "SELECT {$fields}, '{$subset_flu}' `flu_type` FROM {$table}
- WHERE ({$condition_epiweek}) AND ({$condition_location}) AND ({$condition_flu})
- GROUP BY {$group} ORDER BY {$order}";
- execute_query($query, $epidata, $fields_string, $fields_int, null);
- }
- // disjoint flu types: flu1, flu2-flu1, flu3-flu2, ili-flu3
- if(!empty($disjoint_flus)){
- $condition_flu = filter_strings('`flu_type`', $disjoint_flus);
- $query = "SELECT {$fields}, `flu_type` FROM {$table}
- WHERE ({$condition_epiweek}) AND ({$condition_location}) AND ({$condition_flu})
- GROUP BY {$group},`flu_type` ORDER BY {$order},`flu_type`";
- execute_query($query, $epidata, $fields_string, $fields_int, null);
- }
-}
-
-// queries the `nidss_flu` table
-// $epiweeks (required): array of epiweek values/ranges
-// $regions (required): array of region names
-// $issues (optional): array of epiweek values/ranges
-// overrides $lag
-// default: most recent issue
-// $lag (optional): number of weeks between each epiweek and its issue
-// overridden by $issues
-// default: most recent issue
-function get_nidss_flu($epiweeks, $regions, $issues, $lag) {
- // basic query info
- $table = '`nidss_flu` nf';
- $fields = "nf.`release_date`, nf.`issue`, nf.`epiweek`, nf.`region`, nf.`lag`, nf.`visits`, nf.`ili`";
- $order = "nf.`epiweek` ASC, nf.`region` ASC, nf.`issue` ASC";
- // build the epiweek filter
- $condition_epiweek = filter_integers('nf.`epiweek`', $epiweeks);
- // build the region filter
- $condition_region = filter_strings('nf.`region`', $regions);
- if($issues !== null) {
- // build the issue filter
- $condition_issue = filter_integers('nf.`issue`', $issues);
- // final query using specific issues
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) AND ({$condition_issue}) ORDER BY {$order}";
- } else if($lag !== null) {
- // build the lag filter
- $condition_lag = "(nf.`lag` = {$lag})";
- // final query using lagged issues
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) AND ({$condition_lag}) ORDER BY {$order}";
- } else {
- // final query using most recent issues
- $subquery = "(SELECT max(`issue`) `max_issue`, `epiweek`, `region` FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_region}) GROUP BY `epiweek`, `region`) x";
- $condition = "x.`max_issue` = nf.`issue` AND x.`epiweek` = nf.`epiweek` AND x.`region` = nf.`region`";
- $query = "SELECT {$fields} FROM {$table} JOIN {$subquery} ON {$condition} ORDER BY {$order}";
- }
- // get the data from the database
- $epidata = array();
- $fields_string = array('release_date', 'region');
- $fields_int = array('issue', 'epiweek', 'lag', 'visits');
- $fields_float = array('ili');
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `nidss_dengue` table
-// $epiweeks (required): array of epiweek values/ranges
-// $locations (required): array of region and/or location names
-function get_nidss_dengue($epiweeks, $locations) {
- global $dbh;
- // build the epiweek filter
- $condition_epiweek = filter_integers('nd.`epiweek`', $epiweeks);
- // get the data from the database
- $epidata = array();
- $fields_string = array('location');
- $fields_int = array('epiweek', 'count');
- foreach($locations as $location) {
- $location = mysqli_real_escape_string($dbh, $location);
- $query = "
- SELECT
- nd2.`epiweek`, nd2.`location`, count(1) `num_locations`, sum(nd2.`count`) `count`
- FROM (
- SELECT
- nd1.`epiweek`, CASE WHEN q.`query` = nd1.`location` THEN nd1.`location` WHEN q.`query` = nd1.`region` THEN nd1.`region` ELSE nd1.`nat` END `location`, nd1.`count`
- FROM (
- SELECT
- `epiweek`, `location`, `region`, 'nationwide' `nat`, `count`
- FROM
- `nidss_dengue` nd
- WHERE {$condition_epiweek}
- ) nd1
- JOIN (
- SELECT
- '{$location}' `query`
- ) q
- ON
- q.`query` IN (nd1.`location`, nd1.`region`, nd1.`nat`)
- ) nd2
- GROUP BY
- nd2.`epiweek`, nd2.`location`
- ";
- execute_query($query, $epidata, $fields_string, $fields_int, null);
- }
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `forecasts` table
-// $system (required): system name
-// $epiweek (required): epiweek on which the forecast was made
-function get_forecast($system, $epiweek) {
- global $dbh;
- // get the data from the database
- $system = mysqli_real_escape_string($dbh, $system);
- $query = "SELECT `system`, `epiweek`, `json` FROM `forecasts` WHERE `system` = '{$system}' AND `epiweek` = {$epiweek}";
- $epidata = array();
- $fields_string = array('system', 'json');
- $fields_int = array('epiweek');
- execute_query($query, $epidata, $fields_string, $fields_int, null);
- // parse forecast data
- if(count($epidata) === 1 && array_key_exists('json', $epidata[0])) {
- $epidata[0]['forecast'] = json_decode($epidata[0]['json']);
- unset($epidata[0]['json']);
- }
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `cdc_extract` table
-// $epiweeks (required): array of epiweek values/ranges
-// $locations (required): array of location names
-function get_cdc($epiweeks, $locations) {
- global $dbh;
- // basic query info
- $table = '`cdc_extract` c';
- $group = "c.`epiweek`";
- $order = "c.`epiweek` ASC";
- $fields_string = array('location');
- $fields_int = array('epiweek', 'num1', 'num2', 'num3', 'num4', 'num5', 'num6', 'num7', 'num8', 'total');
- // build the epiweek filter
- $condition_epiweek = filter_integers('c.`epiweek`', $epiweeks);
- // split locations into national/regional/state
- $regions = array();
- $states = array();
- foreach($locations as $location) {
- $location = strtolower($location);
- if(in_array($location, array('nat', 'hhs1', 'hhs2', 'hhs3', 'hhs4', 'hhs5', 'hhs6', 'hhs7', 'hhs8', 'hhs9', 'hhs10', 'cen1', 'cen2', 'cen3', 'cen4', 'cen5', 'cen6', 'cen7', 'cen8', 'cen9'))) {
- array_push($regions, $location);
- } else {
- array_push($states, $location);
- }
- }
- // initialize the epidata array
- $epidata = array();
- // query each region type individually (the data is stored by state, so getting regional data requires some extra processing)
- foreach($regions as $region) {
- $region = mysqli_real_escape_string($dbh, $region);
- $fields = "'{$region}' `location`, c.`epiweek`, sum(c.`num1`) `num1`, sum(c.`num2`) `num2`, sum(c.`num3`) `num3`, sum(c.`num4`) `num4`, sum(c.`num5`) `num5`, sum(c.`num6`) `num6`, sum(c.`num7`) `num7`, sum(c.`num8`) `num8`, sum(c.`total`) `total`";
- if($region === 'nat') {
- // final query for U.S. National
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) GROUP BY {$group} ORDER BY {$order}";
- } else {
- // build the location filter
- $condition_location = "`state` IN (" . get_region_states($region) . ")";
- // final query for HHS Regions
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_location}) GROUP BY {$group} ORDER BY {$order}";
- }
- // append query results to the epidata array
- execute_query($query, $epidata, $fields_string, $fields_int, null);
- }
- // query all states together
- if(count($states) !== 0) {
- $fields = "c.`state` `location`, c.`epiweek`, c.`num1`, c.`num2`, c.`num3`, c.`num4`, c.`num5`, c.`num6`, c.`num7`, c.`num8`, c.`total`";
- // build the location filter
- $condition_location = filter_strings('c.`state`', $states);
- // final query for states
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_epiweek}) AND ({$condition_location}) ORDER BY {$order}, c.`state` ASC";
- // append query results to the epidata array
- execute_query($query, $epidata, $fields_string, $fields_int, null);
- }
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `sensors` table
-// $names (required): array of sensor names
-// $locations (required): array of location names
-// $epiweeks (required): array of epiweek values/ranges
-function get_sensors($names, $locations, $epiweeks) {
- // basic query info
- $table = '`sensors` s';
- $fields = "s.`name`, s.`location`, s.`epiweek`, s.`value`";
- $order = "s.`epiweek` ASC, s.`name` ASC, s.`location` ASC";
- // data type of each field
- $fields_string = array('name', 'location');
- $fields_int = array('epiweek');
- $fields_float = array('value');
- // build the name filter
- $condition_name = filter_strings('s.`name`', $names);
- // build the location filter
- $condition_location = filter_strings('s.`location`', $locations);
- // build the epiweek filter
- $condition_epiweek = filter_integers('s.`epiweek`', $epiweeks);
- // the query
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_name}) AND ({$condition_location}) AND ({$condition_epiweek}) ORDER BY {$order}";
- // get the data from the database
- $epidata = array();
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `dengue_sensors` table
-// $names (required): array of sensor names
-// $locations (required): array of location names
-// $epiweeks (required): array of epiweek values/ranges
-function get_dengue_sensors($names, $locations, $epiweeks) {
- // basic query info
- $table = '`dengue_sensors` s';
- $fields = "s.`name`, s.`location`, s.`epiweek`, s.`value`";
- $order = "s.`epiweek` ASC, s.`name` ASC, s.`location` ASC";
- // data type of each field
- $fields_string = array('name', 'location');
- $fields_int = array('epiweek');
- $fields_float = array('value');
- // build the name filter
- $condition_name = filter_strings('s.`name`', $names);
- // build the location filter
- $condition_location = filter_strings('s.`location`', $locations);
- // build the epiweek filter
- $condition_epiweek = filter_integers('s.`epiweek`', $epiweeks);
- // the query
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_name}) AND ({$condition_location}) AND ({$condition_epiweek}) ORDER BY {$order}";
- // get the data from the database
- $epidata = array();
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `nowcasts` table
-// $locations (required): array of location names
-// $epiweeks (required): array of epiweek values/ranges
-function get_nowcast($locations, $epiweeks) {
- // basic query info
- $table = '`nowcasts` n';
- $fields = "n.`location`, n.`epiweek`, n.`value`, n.`std`";
- $order = "n.`epiweek` ASC, n.`location` ASC";
- // data type of each field
- $fields_string = array('location');
- $fields_int = array('epiweek');
- $fields_float = array('value', 'std');
- // build the location filter
- $condition_location = filter_strings('n.`location`', $locations);
- // build the epiweek filter
- $condition_epiweek = filter_integers('n.`epiweek`', $epiweeks);
- // the query
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_location}) AND ({$condition_epiweek}) ORDER BY {$order}";
- // get the data from the database
- $epidata = array();
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `dengue_nowcasts` table
-// $locations (required): array of location names
-// $epiweeks (required): array of epiweek values/ranges
-function get_dengue_nowcast($locations, $epiweeks) {
- // basic query info
- $table = '`dengue_nowcasts` n';
- $fields = "n.`location`, n.`epiweek`, n.`value`, n.`std`";
- $order = "n.`epiweek` ASC, n.`location` ASC";
- // data type of each field
- $fields_string = array('location');
- $fields_int = array('epiweek');
- $fields_float = array('value', 'std');
- // build the location filter
- $condition_location = filter_strings('n.`location`', $locations);
- // build the epiweek filter
- $condition_epiweek = filter_integers('n.`epiweek`', $epiweeks);
- // the query
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_location}) AND ({$condition_epiweek}) ORDER BY {$order}";
- // get the data from the database
- $epidata = array();
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `covidcast` table.
-// $source (required): name of upstream data source
-// $signals (required): array of names for signals derived from upstream data
-// $time_type (required): temporal resolution (e.g. day, week)
-// $geo_type (required): spatial resolution (e.g. county, msa, state)
-// $time_values (required): array of time values/ranges
-// $geo_values (required): string, array of string, or `*` as a wildcard for all
-// locations (specific to `$geo_type`)
-// $issues (optional): array of time values/ranges
-// overrides $lag
-// default: most recent issue
-// $lag (optional): number of time units between each time value and its issue
-// overridden by $issues
-// default: most recent issue
-function get_covidcast($source, $signals, $time_type, $geo_type, $time_values, $geo_values, $as_of, $issues, $lag) {
- // required for `mysqli_real_escape_string`
- global $dbh;
- $source = mysqli_real_escape_string($dbh, $source);
- $time_type = mysqli_real_escape_string($dbh, $time_type);
- $geo_type = mysqli_real_escape_string($dbh, $geo_type);
- // basic query info
- $table = '`covidcast` t';
- $fields = "t.`signal`, t.`time_value`, t.`geo_value`, t.`value`, t.`stderr`, t.`sample_size`, t.`direction`, t.`issue`, t.`lag`, t. `missing_value`, t. `missing_stderr`, t. `missing_sample_size`";
- $order = "t.`signal` ASC, t.`time_value` ASC, t.`geo_value` ASC, t.`issue` ASC";
- // data type of each field
- $fields_string = array('geo_value', 'signal');
- $fields_int = array('time_value', 'direction', 'issue', 'lag', 'missing_value', 'missing_stderr', 'missing_sample_size');
- $fields_float = array('value', 'stderr', 'sample_size');
- // build the source, signal, time, and location (type and id) filters
- $condition_source = "t.`source` = '{$source}'";
- $condition_signal = filter_strings('t.`signal`', $signals);
- $condition_time_type = "t.`time_type` = '{$time_type}'";
- $condition_geo_type = "t.`geo_type` = '{$geo_type}'";
- $condition_time_value = filter_integers('t.`time_value`', $time_values);
-
- if ($geo_values === '*') {
- // the wildcard query should return data for all locations in `geo_type`
- $condition_geo_value = 'TRUE';
- } else if (is_array($geo_values)) {
- // return data for multiple location
- $condition_geo_value = filter_strings('t.`geo_value`', $geo_values);
- } else {
- // return data for a particular location
- $geo_escaped_value = mysqli_real_escape_string($dbh, $geo_values);
- $condition_geo_value = "t.`geo_value` = '{$geo_escaped_value}'";
- }
- $conditions = "({$condition_source}) AND ({$condition_signal}) AND ({$condition_time_type}) AND ({$condition_geo_type}) AND ({$condition_time_value}) AND ({$condition_geo_value})";
-
- $subquery = "";
- if ($issues !== null) {
- //build the issue filter
- $condition_issue = filter_integers('t.`issue`', $issues);
- $condition_version = $condition_issue;
- } else if ($lag !== null) {
- //build the lag filter
- $condition_lag = "(t.`lag` = {$lag})";
- $condition_version = $condition_lag;
- } else if ($as_of !== null) {
- // fetch most recent issues with as of
- $sub_condition_asof = "(`issue` <= {$as_of})";
- $sub_fields = "max(`issue`) `max_issue`, `time_type`, `time_value`, `source`, `signal`, `geo_type`, `geo_value`";
- $sub_group = "`time_type`, `time_value`, `source`, `signal`, `geo_type`, `geo_value`";
- $sub_condition = "x.`max_issue` = t.`issue` AND x.`time_type` = t.`time_type` AND x.`time_value` = t.`time_value` AND x.`source` = t.`source` AND x.`signal` = t.`signal` AND x.`geo_type` = t.`geo_type` AND x.`geo_value` = t.`geo_value`";
- $subquery = "JOIN (SELECT {$sub_fields} FROM {$table} WHERE ({$conditions} AND {$sub_condition_asof}) GROUP BY {$sub_group}) x ON {$sub_condition}";
- $condition_version = 'TRUE';
- } else {
- // fetch most recent issue fast
- $condition_version = '(t.`is_latest_issue` IS TRUE)';
- }
- // the query
- $query = "SELECT {$fields} FROM {$table} {$subquery} WHERE {$conditions} AND ({$condition_version}) ORDER BY {$order}";
- // get the data from the database
- $epidata = array();
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-function get_signal_dash_status_data() {
- $query = 'SELECT enabled_signal.`name`,
- enabled_signal.`source`,
- enabled_signal.`covidcast_signal`,
- status.`latest_issue`,
- status.`latest_time_value`
- FROM (SELECT `id`, `name`, `source`, `covidcast_signal`, `latest_status_update`
- FROM `dashboard_signal`
- WHERE `enabled`) AS enabled_signal
- LEFT JOIN `dashboard_signal_status` AS status
- ON enabled_signal.`latest_status_update` = status.`date`
- AND enabled_signal.`id` = status.`signal_id`';
-
- $epidata = array();
- $fields_string = array('name', 'source', 'covidcast_signal', 'latest_issue', 'latest_time_value');
- execute_query($query, $epidata, $fields_string, null /* fields_int */, null /* fields_float */);
-
- $coverage = get_signal_dash_coverage_data();
-
- $out = array();
- foreach ($epidata as $signal) {
- if (isset($coverage[$signal['name']])) {
- $signal_with_coverage = $signal;
- $signal_with_coverage['coverage'] = $coverage[$signal['name']];
- $out[] = $signal_with_coverage;
- }
- }
-
- // return the data
- return count($out) === 0 ? null : $out;
-}
-
-function get_signal_dash_coverage_data() {
- $query = 'SELECT enabled_signal.`name`,
- coverage.`date`,
- coverage.`geo_type`,
- coverage.`count`
- FROM (SELECT `id`, `name`, `latest_coverage_update`
- FROM `dashboard_signal`
- WHERE `enabled`) AS enabled_signal
- LEFT JOIN `dashboard_signal_coverage` AS coverage
- ON enabled_signal.`id` = coverage.`signal_id`
- ORDER BY `id` ASC, `date` DESC';
-
- $epidata = array();
- $fields_string = array('name', 'date', 'geo_type');
- $fields_int = array('count');
- execute_query($query, $epidata, $fields_string, $fields_int, null /* fields_float */);
-
- $out = array();
- foreach ($epidata as $row) {
- $name = $row['name'];
- $geo_type = $row['geo_type'];
- $timedata = array();
- $timedata['date'] = $row['date'];
- $timedata['count'] =$row['count'];
-
- if (!isset($out[$name])) {
- $out[$name] = array();
- }
-
- if(!isset($out[$name][$geo_type])) {
- $out[$name][$geo_type] = array();
- }
-
- $out[$name][$geo_type][] = $timedata;
- }
-
- // return the data
- return count($out) === 0 ? null : $out;
-}
-
-// queries the `covidcast_meta_cache` table for metadata
-function get_covidcast_meta() {
- // complain if the cache is more than 75 minutes old
- $max_age = 75 * 60;
-
- // basic query info
- $query = 'SELECT UNIX_TIMESTAMP(NOW()) - `timestamp` AS `age`, `epidata` FROM `covidcast_meta_cache` LIMIT 1';
-
- // get the data from the database
- global $dbh;
- $epidata = null;
- $result = mysqli_query($dbh, $query);
- if($row = mysqli_fetch_array($result)) {
- // parse and use the cached response
- $epidata = json_decode($row['epidata'], true);
-
- if (intval($row['age']) > $max_age && strlen($row['epidata']) > 0) {
- error_log('covidcast_meta cache is stale: '.$row['age']);
- }
- }
-
- if ($epidata !== null) {
- // filter rows
- $time_types = extract_values($_REQUEST['time_types'], 'str');
- $signals = isset($_REQUEST['signals']) ? array_map(function($signal) {
- return explode(':', $signal, 2);
- }, extract_values($_REQUEST['signals'], 'str')) : null;
- $geo_types = extract_values($_REQUEST['geo_types'], 'str');
-
- if ($time_types !== null || $signals !== null || $geo_types !== null) {
- $epidata = array_values(array_filter($epidata, function($row) use(&$time_types, &$signals, &$geo_types) {
- if ($time_types !== null && !in_array($row['time_type'], $time_types)) {
- return false;
- }
- if ($geo_types !== null && !in_array($row['geo_type'], $geo_types)) {
- return false;
- }
- if ($signals === null || count($signals) === 0) {
- return true;
- }
- // filter by signal
- foreach($signals as $signal) {
- // match source and (signal or no signal or signal = *)
- if ($row['data_source'] === $signal[0] && (count($signal) === 1 || $row['signal'] === $signal[1] || $signal[1] === '*')) {
- return true;
- }
- }
- return false;
- }));
- }
- // filter fields
- if (isset($_REQUEST['fields'])) {
- $fields = extract_values($_REQUEST['fields'], 'str');
-
- $epidata = array_map(function($row) use(&$fields) {
- $filtered_row = [];
- foreach($fields as $field) {
- if (isset($row[$field])) {
- $filtered_row[$field] = $row[$field];
- }
- }
- return $filtered_row;
- }, $epidata);
- }
- }
-
- // return the data
- $has_values = $epidata !== null && count($epidata) > 0;
- return $has_values ? $epidata : null;
-}
-
-// queries the `covid_hosp_state_timeseries` table
-// $states (required): array of state abbreviations
-// $dates (required): array of date values/ranges
-// $issues (optional): array of date values/ranges
-// default: most recent issue
-function get_covid_hosp_state_timeseries($states, $dates, $issues) {
- $epidata = array();
- $table = '`covid_hosp_state_timeseries` c';
- $fields = implode(', ', array(
- 'c.`issue`',
- 'c.`state`',
- 'c.`date`',
- 'c.`critical_staffing_shortage_today_yes`',
- 'c.`critical_staffing_shortage_today_no`',
- 'c.`critical_staffing_shortage_today_not_reported`',
- 'c.`critical_staffing_shortage_anticipated_within_week_yes`',
- 'c.`critical_staffing_shortage_anticipated_within_week_no`',
- 'c.`critical_staffing_shortage_anticipated_within_week_not_reported`',
- 'c.`hospital_onset_covid`',
- 'c.`hospital_onset_covid_coverage`',
- 'c.`inpatient_beds`',
- 'c.`inpatient_beds_coverage`',
- 'c.`inpatient_beds_used`',
- 'c.`inpatient_beds_used_coverage`',
- 'c.`inpatient_beds_used_covid`',
- 'c.`inpatient_beds_used_covid_coverage`',
- 'c.`previous_day_admission_adult_covid_confirmed`',
- 'c.`previous_day_admission_adult_covid_confirmed_coverage`',
- 'c.`previous_day_admission_adult_covid_suspected`',
- 'c.`previous_day_admission_adult_covid_suspected_coverage`',
- 'c.`previous_day_admission_pediatric_covid_confirmed`',
- 'c.`previous_day_admission_pediatric_covid_confirmed_coverage`',
- 'c.`previous_day_admission_pediatric_covid_suspected`',
- 'c.`previous_day_admission_pediatric_covid_suspected_coverage`',
- 'c.`staffed_adult_icu_bed_occupancy`',
- 'c.`staffed_adult_icu_bed_occupancy_coverage`',
- 'c.`staffed_icu_adult_patients_confirmed_suspected_covid`',
- 'c.`staffed_icu_adult_patients_confirmed_suspected_covid_coverage`',
- 'c.`staffed_icu_adult_patients_confirmed_covid`',
- 'c.`staffed_icu_adult_patients_confirmed_covid_coverage`',
- 'c.`total_adult_patients_hosp_confirmed_suspected_covid`',
- 'c.`total_adult_patients_hosp_confirmed_suspected_covid_coverage`',
- 'c.`total_adult_patients_hosp_confirmed_covid`',
- 'c.`total_adult_patients_hosp_confirmed_covid_coverage`',
- 'c.`total_pediatric_patients_hosp_confirmed_suspected_covid`',
- 'c.`total_pediatric_patients_hosp_confirmed_suspected_covid_coverage`',
- 'c.`total_pediatric_patients_hosp_confirmed_covid`',
- 'c.`total_pediatric_patients_hosp_confirmed_covid_coverage`',
- 'c.`total_staffed_adult_icu_beds`',
- 'c.`total_staffed_adult_icu_beds_coverage`',
- 'c.`inpatient_beds_utilization`',
- 'c.`inpatient_beds_utilization_coverage`',
- 'c.`inpatient_beds_utilization_numerator`',
- 'c.`inpatient_beds_utilization_denominator`',
- 'c.`percent_of_inpatients_with_covid`',
- 'c.`percent_of_inpatients_with_covid_coverage`',
- 'c.`percent_of_inpatients_with_covid_numerator`',
- 'c.`percent_of_inpatients_with_covid_denominator`',
- 'c.`inpatient_bed_covid_utilization`',
- 'c.`inpatient_bed_covid_utilization_coverage`',
- 'c.`inpatient_bed_covid_utilization_numerator`',
- 'c.`inpatient_bed_covid_utilization_denominator`',
- 'c.`adult_icu_bed_covid_utilization`',
- 'c.`adult_icu_bed_covid_utilization_coverage`',
- 'c.`adult_icu_bed_covid_utilization_numerator`',
- 'c.`adult_icu_bed_covid_utilization_denominator`',
- 'c.`adult_icu_bed_utilization`',
- 'c.`adult_icu_bed_utilization_coverage`',
- 'c.`adult_icu_bed_utilization_numerator`',
- 'c.`adult_icu_bed_utilization_denominator`',
- ));
- // basic query info
- $order = "c.`date` ASC, c.`state` ASC, c.`issue` ASC";
- // build the date filter
- $condition_date = filter_integers('c.`date`', $dates);
- // build the state filter
- $condition_state = filter_strings('c.`state`', $states);
- if($issues !== null) {
- // build the issue filter
- $condition_issue = filter_integers('c.`issue`', $issues);
- // final query using specific issues
- $query = "WITH c as (SELECT {$fields}, ROW_NUMBER() OVER (PARTITION BY date, state, issue ORDER BY record_type) row FROM {$table} WHERE ({$condition_date}) AND ({$condition_state}) AND ({$condition_issue})) SELECT {$fields} FROM c where row = 1 ORDER BY {$order}";
- } else {
- // final query using most recent issues
- $subquery = "(SELECT max(`issue`) `max_issue`, `date`, `state` FROM {$table} WHERE ({$condition_date}) AND ({$condition_state}) GROUP BY `date`, `state`) x";
- $condition = "x.`max_issue` = c.`issue` AND x.`date` = c.`date` AND x.`state` = c.`state`";
- $query = "WITH c as (SELECT {$fields}, ROW_NUMBER() OVER (PARTITION BY date, state, issue ORDER BY record_type) row FROM {$table} JOIN {$subquery} ON {$condition}) select {$fields} FROM c WHERE row = 1 ORDER BY {$order}";
- }
- // get the data from the database
- $fields_string = array('state');
- $fields_int = array(
- 'issue',
- 'date',
- 'critical_staffing_shortage_today_yes',
- 'critical_staffing_shortage_today_no',
- 'critical_staffing_shortage_today_not_reported',
- 'critical_staffing_shortage_anticipated_within_week_yes',
- 'critical_staffing_shortage_anticipated_within_week_no',
- 'critical_staffing_shortage_anticipated_within_week_not_reported',
- 'hospital_onset_covid',
- 'hospital_onset_covid_coverage',
- 'inpatient_beds',
- 'inpatient_beds_coverage',
- 'inpatient_beds_used',
- 'inpatient_beds_used_coverage',
- 'inpatient_beds_used_covid',
- 'inpatient_beds_used_covid_coverage',
- 'previous_day_admission_adult_covid_confirmed',
- 'previous_day_admission_adult_covid_confirmed_coverage',
- 'previous_day_admission_adult_covid_suspected',
- 'previous_day_admission_adult_covid_suspected_coverage',
- 'previous_day_admission_pediatric_covid_confirmed',
- 'previous_day_admission_pediatric_covid_confirmed_coverage',
- 'previous_day_admission_pediatric_covid_suspected',
- 'previous_day_admission_pediatric_covid_suspected_coverage',
- 'staffed_adult_icu_bed_occupancy',
- 'staffed_adult_icu_bed_occupancy_coverage',
- 'staffed_icu_adult_patients_confirmed_suspected_covid',
- 'staffed_icu_adult_patients_confirmed_suspected_covid_coverage',
- 'staffed_icu_adult_patients_confirmed_covid',
- 'staffed_icu_adult_patients_confirmed_covid_coverage',
- 'total_adult_patients_hosp_confirmed_suspected_covid',
- 'total_adult_patients_hosp_confirmed_suspected_covid_coverage',
- 'total_adult_patients_hosp_confirmed_covid',
- 'total_adult_patients_hosp_confirmed_covid_coverage',
- 'total_pediatric_patients_hosp_confirmed_suspected_covid',
- 'total_pediatric_patients_hosp_confirmed_suspected_covid_coverage',
- 'total_pediatric_patients_hosp_confirmed_covid',
- 'total_pediatric_patients_hosp_confirmed_covid_coverage',
- 'total_staffed_adult_icu_beds',
- 'total_staffed_adult_icu_beds_coverage',
- 'inpatient_beds_utilization_coverage',
- 'inpatient_beds_utilization_numerator',
- 'inpatient_beds_utilization_denominator',
- 'percent_of_inpatients_with_covid_coverage',
- 'percent_of_inpatients_with_covid_numerator',
- 'percent_of_inpatients_with_covid_denominator',
- 'inpatient_bed_covid_utilization_coverage',
- 'inpatient_bed_covid_utilization_numerator',
- 'inpatient_bed_covid_utilization_denominator',
- 'adult_icu_bed_covid_utilization_coverage',
- 'adult_icu_bed_covid_utilization_numerator',
- 'adult_icu_bed_covid_utilization_denominator',
- 'adult_icu_bed_utilization_coverage',
- 'adult_icu_bed_utilization_numerator',
- 'adult_icu_bed_utilization_denominator',
- );
- $fields_float = array(
- 'inpatient_beds_utilization',
- 'percent_of_inpatients_with_covid',
- 'inpatient_bed_covid_utilization',
- 'adult_icu_bed_covid_utilization',
- 'adult_icu_bed_utilization',
- );
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `covid_hosp_facility` table
-// $hospital_pks (required): array of facility identifiers (`hospital_pk`)
-// $collection_weeks (required): array of date values/ranges
-// $publication_dates (optional): array of date values/ranges
-// default: most recent issue
-function get_covid_hosp_facility($hospital_pks, $collection_weeks, $publication_dates) {
- $epidata = array();
- $table = '`covid_hosp_facility` c';
- $fields = implode(', ', array(
- 'c.`publication_date`',
- 'c.`hospital_pk`',
- 'c.`collection_week`',
- 'c.`state`',
- 'c.`ccn`',
- 'c.`hospital_name`',
- 'c.`address`',
- 'c.`city`',
- 'c.`zip`',
- 'c.`hospital_subtype`',
- 'c.`fips_code`',
- 'c.`is_metro_micro`',
- 'c.`total_beds_7_day_avg`',
- 'c.`all_adult_hospital_beds_7_day_avg`',
- 'c.`all_adult_hospital_inpatient_beds_7_day_avg`',
- 'c.`inpatient_beds_used_7_day_avg`',
- 'c.`all_adult_hospital_inpatient_bed_occupied_7_day_avg`',
- 'c.`total_adult_patients_hosp_confirmed_suspected_covid_7d_avg`',
- 'c.`total_adult_patients_hospitalized_confirmed_covid_7_day_avg`',
- 'c.`total_pediatric_patients_hosp_confirmed_suspected_covid_7d_avg`',
- 'c.`total_pediatric_patients_hospitalized_confirmed_covid_7_day_avg`',
- 'c.`inpatient_beds_7_day_avg`',
- 'c.`total_icu_beds_7_day_avg`',
- 'c.`total_staffed_adult_icu_beds_7_day_avg`',
- 'c.`icu_beds_used_7_day_avg`',
- 'c.`staffed_adult_icu_bed_occupancy_7_day_avg`',
- 'c.`staffed_icu_adult_patients_confirmed_suspected_covid_7d_avg`',
- 'c.`staffed_icu_adult_patients_confirmed_covid_7_day_avg`',
- 'c.`total_patients_hospitalized_confirmed_influenza_7_day_avg`',
- 'c.`icu_patients_confirmed_influenza_7_day_avg`',
- 'c.`total_patients_hosp_confirmed_influenza_and_covid_7d_avg`',
- 'c.`total_beds_7_day_sum`',
- 'c.`all_adult_hospital_beds_7_day_sum`',
- 'c.`all_adult_hospital_inpatient_beds_7_day_sum`',
- 'c.`inpatient_beds_used_7_day_sum`',
- 'c.`all_adult_hospital_inpatient_bed_occupied_7_day_sum`',
- 'c.`total_adult_patients_hosp_confirmed_suspected_covid_7d_sum`',
- 'c.`total_adult_patients_hospitalized_confirmed_covid_7_day_sum`',
- 'c.`total_pediatric_patients_hosp_confirmed_suspected_covid_7d_sum`',
- 'c.`total_pediatric_patients_hospitalized_confirmed_covid_7_day_sum`',
- 'c.`inpatient_beds_7_day_sum`',
- 'c.`total_icu_beds_7_day_sum`',
- 'c.`total_staffed_adult_icu_beds_7_day_sum`',
- 'c.`icu_beds_used_7_day_sum`',
- 'c.`staffed_adult_icu_bed_occupancy_7_day_sum`',
- 'c.`staffed_icu_adult_patients_confirmed_suspected_covid_7d_sum`',
- 'c.`staffed_icu_adult_patients_confirmed_covid_7_day_sum`',
- 'c.`total_patients_hospitalized_confirmed_influenza_7_day_sum`',
- 'c.`icu_patients_confirmed_influenza_7_day_sum`',
- 'c.`total_patients_hosp_confirmed_influenza_and_covid_7d_sum`',
- 'c.`total_beds_7_day_coverage`',
- 'c.`all_adult_hospital_beds_7_day_coverage`',
- 'c.`all_adult_hospital_inpatient_beds_7_day_coverage`',
- 'c.`inpatient_beds_used_7_day_coverage`',
- 'c.`all_adult_hospital_inpatient_bed_occupied_7_day_coverage`',
- 'c.`total_adult_patients_hosp_confirmed_suspected_covid_7d_cov`',
- 'c.`total_adult_patients_hospitalized_confirmed_covid_7_day_coverage`',
- 'c.`total_pediatric_patients_hosp_confirmed_suspected_covid_7d_cov`',
- 'c.`total_pediatric_patients_hosp_confirmed_covid_7d_cov`',
- 'c.`inpatient_beds_7_day_coverage`',
- 'c.`total_icu_beds_7_day_coverage`',
- 'c.`total_staffed_adult_icu_beds_7_day_coverage`',
- 'c.`icu_beds_used_7_day_coverage`',
- 'c.`staffed_adult_icu_bed_occupancy_7_day_coverage`',
- 'c.`staffed_icu_adult_patients_confirmed_suspected_covid_7d_cov`',
- 'c.`staffed_icu_adult_patients_confirmed_covid_7_day_coverage`',
- 'c.`total_patients_hospitalized_confirmed_influenza_7_day_coverage`',
- 'c.`icu_patients_confirmed_influenza_7_day_coverage`',
- 'c.`total_patients_hosp_confirmed_influenza_and_covid_7d_cov`',
- 'c.`previous_day_admission_adult_covid_confirmed_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_confirmed_18_19_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_confirmed_20_29_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_confirmed_30_39_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_confirmed_40_49_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_confirmed_50_59_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_confirmed_60_69_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_confirmed_70_79_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_confirmed_80plus_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_confirmed_unknown_7_day_sum`',
- 'c.`previous_day_admission_pediatric_covid_confirmed_7_day_sum`',
- 'c.`previous_day_covid_ed_visits_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_suspected_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_suspected_18_19_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_suspected_20_29_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_suspected_30_39_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_suspected_40_49_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_suspected_50_59_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_suspected_60_69_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_suspected_70_79_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_suspected_80plus_7_day_sum`',
- 'c.`previous_day_admission_adult_covid_suspected_unknown_7_day_sum`',
- 'c.`previous_day_admission_pediatric_covid_suspected_7_day_sum`',
- 'c.`previous_day_total_ed_visits_7_day_sum`',
- 'c.`previous_day_admission_influenza_confirmed_7_day_sum`',
- ));
- // basic query info
- $order = "c.`collection_week` ASC, c.`hospital_pk` ASC, c.`publication_date` ASC";
- // build the date filter
- $condition_collection_week = filter_integers('c.`collection_week`', $collection_weeks);
- // build the state filter
- $condition_hospital_pk = filter_strings('c.`hospital_pk`', $hospital_pks);
- if($publication_dates !== null) {
- // build the issue filter
- $condition_publication_date = filter_integers('c.`publication_date`', $publication_dates);
- // final query using specific issues
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition_collection_week}) AND ({$condition_hospital_pk}) AND ({$condition_publication_date}) ORDER BY {$order}";
- } else {
- // final query using most recent issues
- $subquery = "(SELECT max(`publication_date`) `max_publication_date`, `collection_week`, `hospital_pk` FROM {$table} WHERE ({$condition_collection_week}) AND ({$condition_hospital_pk}) GROUP BY `collection_week`, `hospital_pk`) x";
- $condition = "x.`max_publication_date` = c.`publication_date` AND x.`collection_week` = c.`collection_week` AND x.`hospital_pk` = c.`hospital_pk`";
- $query = "SELECT {$fields} FROM {$table} JOIN {$subquery} ON {$condition} ORDER BY {$order}";
- }
- // get the data from the database
- $fields_string = array(
- 'hospital_pk',
- 'state',
- 'ccn',
- 'hospital_name',
- 'address',
- 'city',
- 'zip',
- 'hospital_subtype',
- 'fips_code',
- );
- $fields_int = array(
- 'publication_date',
- 'collection_week',
- 'is_metro_micro',
- 'total_beds_7_day_sum',
- 'all_adult_hospital_beds_7_day_sum',
- 'all_adult_hospital_inpatient_beds_7_day_sum',
- 'inpatient_beds_used_7_day_sum',
- 'all_adult_hospital_inpatient_bed_occupied_7_day_sum',
- 'total_adult_patients_hosp_confirmed_suspected_covid_7d_sum',
- 'total_adult_patients_hospitalized_confirmed_covid_7_day_sum',
- 'total_pediatric_patients_hosp_confirmed_suspected_covid_7d_sum',
- 'total_pediatric_patients_hospitalized_confirmed_covid_7_day_sum',
- 'inpatient_beds_7_day_sum',
- 'total_icu_beds_7_day_sum',
- 'total_staffed_adult_icu_beds_7_day_sum',
- 'icu_beds_used_7_day_sum',
- 'staffed_adult_icu_bed_occupancy_7_day_sum',
- 'staffed_icu_adult_patients_confirmed_suspected_covid_7d_sum',
- 'staffed_icu_adult_patients_confirmed_covid_7_day_sum',
- 'total_patients_hospitalized_confirmed_influenza_7_day_sum',
- 'icu_patients_confirmed_influenza_7_day_sum',
- 'total_patients_hosp_confirmed_influenza_and_covid_7d_sum',
- 'total_beds_7_day_coverage',
- 'all_adult_hospital_beds_7_day_coverage',
- 'all_adult_hospital_inpatient_beds_7_day_coverage',
- 'inpatient_beds_used_7_day_coverage',
- 'all_adult_hospital_inpatient_bed_occupied_7_day_coverage',
- 'total_adult_patients_hosp_confirmed_suspected_covid_7d_cov',
- 'total_adult_patients_hospitalized_confirmed_covid_7_day_coverage',
- 'total_pediatric_patients_hosp_confirmed_suspected_covid_7d_cov',
- 'total_pediatric_patients_hosp_confirmed_covid_7d_cov',
- 'inpatient_beds_7_day_coverage',
- 'total_icu_beds_7_day_coverage',
- 'total_staffed_adult_icu_beds_7_day_coverage',
- 'icu_beds_used_7_day_coverage',
- 'staffed_adult_icu_bed_occupancy_7_day_coverage',
- 'staffed_icu_adult_patients_confirmed_suspected_covid_7d_cov',
- 'staffed_icu_adult_patients_confirmed_covid_7_day_coverage',
- 'total_patients_hospitalized_confirmed_influenza_7_day_coverage',
- 'icu_patients_confirmed_influenza_7_day_coverage',
- 'total_patients_hosp_confirmed_influenza_and_covid_7d_cov',
- 'previous_day_admission_adult_covid_confirmed_7_day_sum',
- 'previous_day_admission_adult_covid_confirmed_18_19_7_day_sum',
- 'previous_day_admission_adult_covid_confirmed_20_29_7_day_sum',
- 'previous_day_admission_adult_covid_confirmed_30_39_7_day_sum',
- 'previous_day_admission_adult_covid_confirmed_40_49_7_day_sum',
- 'previous_day_admission_adult_covid_confirmed_50_59_7_day_sum',
- 'previous_day_admission_adult_covid_confirmed_60_69_7_day_sum',
- 'previous_day_admission_adult_covid_confirmed_70_79_7_day_sum',
- 'previous_day_admission_adult_covid_confirmed_80plus_7_day_sum',
- 'previous_day_admission_adult_covid_confirmed_unknown_7_day_sum',
- 'previous_day_admission_pediatric_covid_confirmed_7_day_sum',
- 'previous_day_covid_ed_visits_7_day_sum',
- 'previous_day_admission_adult_covid_suspected_7_day_sum',
- 'previous_day_admission_adult_covid_suspected_18_19_7_day_sum',
- 'previous_day_admission_adult_covid_suspected_20_29_7_day_sum',
- 'previous_day_admission_adult_covid_suspected_30_39_7_day_sum',
- 'previous_day_admission_adult_covid_suspected_40_49_7_day_sum',
- 'previous_day_admission_adult_covid_suspected_50_59_7_day_sum',
- 'previous_day_admission_adult_covid_suspected_60_69_7_day_sum',
- 'previous_day_admission_adult_covid_suspected_70_79_7_day_sum',
- 'previous_day_admission_adult_covid_suspected_80plus_7_day_sum',
- 'previous_day_admission_adult_covid_suspected_unknown_7_day_sum',
- 'previous_day_admission_pediatric_covid_suspected_7_day_sum',
- 'previous_day_total_ed_visits_7_day_sum',
- 'previous_day_admission_influenza_confirmed_7_day_sum',
- );
- $fields_float = array(
- 'total_beds_7_day_avg',
- 'all_adult_hospital_beds_7_day_avg',
- 'all_adult_hospital_inpatient_beds_7_day_avg',
- 'inpatient_beds_used_7_day_avg',
- 'all_adult_hospital_inpatient_bed_occupied_7_day_avg',
- 'total_adult_patients_hosp_confirmed_suspected_covid_7d_avg',
- 'total_adult_patients_hospitalized_confirmed_covid_7_day_avg',
- 'total_pediatric_patients_hosp_confirmed_suspected_covid_7d_avg',
- 'total_pediatric_patients_hospitalized_confirmed_covid_7_day_avg',
- 'inpatient_beds_7_day_avg',
- 'total_icu_beds_7_day_avg',
- 'total_staffed_adult_icu_beds_7_day_avg',
- 'icu_beds_used_7_day_avg',
- 'staffed_adult_icu_bed_occupancy_7_day_avg',
- 'staffed_icu_adult_patients_confirmed_suspected_covid_7d_avg',
- 'staffed_icu_adult_patients_confirmed_covid_7_day_avg',
- 'total_patients_hospitalized_confirmed_influenza_7_day_avg',
- 'icu_patients_confirmed_influenza_7_day_avg',
- 'total_patients_hosp_confirmed_influenza_and_covid_7d_avg',
- );
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries the `covid_hosp_facility` table for hospital discovery
-// $state (optional): 2-letter state abbreviation
-// $ccn (optional): cms certification number (ccn) of the given facility
-// $city (optional): name of
-// $zip (optional): 2-letter state abbreviation
-// $fips_code (optional): 2-letter state abbreviation
-// note: exactly one of the above parameters should be non-null. if more than
-// one is non-null, then only the first filter will be used.
-function get_covid_hosp_facility_lookup($state, $ccn, $city, $zip, $fips_code) {
- $epidata = array();
- $table = '`covid_hosp_facility` c';
- $fields = implode(', ', array(
- 'c.`hospital_pk`',
- 'MAX(c.`state`) `state`',
- 'MAX(c.`ccn`) `ccn`',
- 'MAX(c.`hospital_name`) `hospital_name`',
- 'MAX(c.`address`) `address`',
- 'MAX(c.`city`) `city`',
- 'MAX(c.`zip`) `zip`',
- 'MAX(c.`hospital_subtype`) `hospital_subtype`',
- 'MAX(c.`fips_code`) `fips_code`',
- 'MAX(c.`is_metro_micro`) `is_metro_micro`',
- ));
- // basic query info
- $group = 'c.`hospital_pk`';
- $order = "c.`hospital_pk` ASC";
- // build the filter
- // these are all fast because the table has indexes on each of these fields
- $condition = 'FALSE';
- if ($state !== null) {
- $condition = filter_strings('c.`state`', $state);
- } else if ($ccn !== null) {
- $condition = filter_strings('c.`ccn`', $ccn);
- } else if ($city !== null) {
- $condition = filter_strings('c.`city`', $city);
- } else if ($zip !== null) {
- $condition = filter_strings('c.`zip`', $zip);
- } else if ($fips_code !== null) {
- $condition = filter_strings('c.`fips_code`', $fips_code);
- }
- // final query using specific issues
- $query = "SELECT {$fields} FROM {$table} WHERE ({$condition}) GROUP BY {$group} ORDER BY {$order}";
- // get the data from the database
- $fields_string = array(
- 'hospital_pk',
- 'state',
- 'ccn',
- 'hospital_name',
- 'address',
- 'city',
- 'zip',
- 'hospital_subtype',
- 'fips_code',
- );
- $fields_int = array('is_metro_micro');
- $fields_float = null;
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-// queries a bunch of epidata tables
-function get_meta() {
- // query and return metadata
- return array(array(
- '_api' => array(
- 'minute' => meta_api(60),
- 'hour' => meta_api(60 * 60),
- 'day' => meta_api(60 * 60 * 24),
- 'week' => meta_api(60 * 60 * 24 * 7),
- 'month' => meta_api(60 * 60 * 24 * 30),
- ),
- 'fluview' => meta_fluview(),
- 'twitter' => meta_twitter(),
- 'wiki' => meta_wiki(),
- 'delphi' => meta_delphi(),
- ));
-}
-function meta_api($seconds) {
- $epidata = array();
- $seconds = intval($seconds);
- $query = "SELECT count(1) `num_hits`, count(distinct `ip`) `unique_ips`, sum(`num_rows`) `rows_returned` FROM `api_analytics` WHERE `datetime` >= date_sub(now(), interval {$seconds} second)";
- $fields_int = array('num_hits', 'unique_ips', 'rows_returned');
- execute_query($query, $epidata, null, $fields_int, null);
- return count($epidata) === 0 ? null : $epidata;
-}
-function meta_fluview() {
- $epidata = array();
- $query = 'SELECT max(`release_date`) `latest_update`, max(`issue`) `latest_issue`, count(1) `table_rows` FROM `fluview`';
- $fields_string = array('latest_update');
- $fields_int = array('latest_issue', 'table_rows');
- execute_query($query, $epidata, $fields_string, $fields_int, null);
- return count($epidata) === 0 ? null : $epidata;
-}
-function meta_twitter() {
- $epidata = array();
- $query = 'SELECT x.`date` `latest_update`, x.`table_rows`, count(distinct t.`state`) `num_states` FROM (SELECT max(`date`) `date`, count(1) `table_rows` FROM `twitter`) x JOIN `twitter` t ON t.`date` = x.`date`';
- $fields_string = array('latest_update');
- $fields_int = array('num_states', 'table_rows');
- execute_query($query, $epidata, $fields_string, $fields_int, null);
- return count($epidata) === 0 ? null : $epidata;
-}
-function meta_wiki() {
- $epidata = array();
- //$query = 'SELECT date_sub(max(`datetime`), interval 5 hour) `latest_update`, count(1) `table_rows` FROM `wiki_meta`'; // GMT to EST
- $query = 'SELECT max(`datetime`) `latest_update`, count(1) `table_rows` FROM `wiki_meta`';
- $fields_string = array('latest_update');
- $fields_int = array('table_rows');
- execute_query($query, $epidata, $fields_string, $fields_int, null);
- return count($epidata) === 0 ? null : $epidata;
-}
-function get_meta_norostat() {
- // put behind appropriate auth check
- $epidata_releases = array();
- $query = 'SELECT DISTINCT `release_date` FROM `norostat_raw_datatable_version_list`';
- execute_query($query, $epidata_releases, array('release_date'), null, null);
- $epidata_locations = array();
- $query = 'SELECT DISTINCT `location` FROM `norostat_raw_datatable_location_pool`';
- execute_query($query, $epidata_locations, array('location'), null, null);
- $epidata = array(
- "releases" => $epidata_releases,
- "locations" => $epidata_locations
- );
- return $epidata;
-}
-function get_meta_afhsb() {
- // put behind appropriate auth check
- $table1 = 'afhsb_00to13_state';
- $table2 = 'afhsb_13to17_state';
- $epidata = array();
- $string_keys = array('state', 'country');
- $int_keys = array('flu_severity');
- foreach($string_keys as $key) {
- $epidata_key = array();
- $query = "SELECT DISTINCT `{$key}` FROM (select `{$key}` from `{$table1}` union select `{$key}` from `{$table2}`) t";
- execute_query($query, $epidata_key, array($key), null, null);
- $epidata[$key] = $epidata_key;
- }
- foreach($int_keys as $key) {
- $epidata_key = array();
- $query = "SELECT DISTINCT `{$key}` FROM (select `{$key}` from `{$table1}` union select `{$key}` from `{$table2}`) t";
-
- execute_query($query, $epidata_key, null, array($key), null);
- $epidata[$key] = $epidata_key;
- }
- return $epidata;
-}
-function meta_delphi() {
- $epidata = array();
- $query = 'SELECT `system`, min(`epiweek`) `first_week`, max(`epiweek`) `last_week`, count(1) `num_weeks` FROM `forecasts` GROUP BY `system` ORDER BY `system` ASC';
- $fields_string = array('system');
- $fields_int = array('first_week', 'last_week', 'num_weeks');
- execute_query($query, $epidata, $fields_string, $fields_int, null);
- return count($epidata) === 0 ? null : $epidata;
-}
-
-function get_covidcast_nowcast($source, $signals, $sensor_names, $time_type, $geo_type, $time_values, $geo_values, $as_of, $issues, $lag) {
- // required for `mysqli_real_escape_string`
- global $dbh;
- $source = mysqli_real_escape_string($dbh, $source);
- $time_type = mysqli_real_escape_string($dbh, $time_type);
- $geo_type = mysqli_real_escape_string($dbh, $geo_type);
- // basic query info
- $table = '`covidcast_nowcast` t';
- $fields = "t.`signal`, t.`time_value`, t.`geo_value`, t.`value`, t.`issue`, t.`lag`";
- $order = "t.`signal` ASC, t.`time_value` ASC, t.`geo_value` ASC, t.`issue` ASC";
- // data type of each field
- $fields_string = array('geo_value', 'signal');
- $fields_int = array('time_value', 'issue', 'lag');
- $fields_float = array('value');
- // build the source, signal, time, and location (type and id) filters
- $condition_source = "t.`source` = '{$source}'";
- $condition_signal = filter_strings('t.`signal`', $signals);
- $condition_sensor_name = filter_strings('t.`sensor_name`', $sensor_names);
- $condition_time_type = "t.`time_type` = '{$time_type}'";
- $condition_geo_type = "t.`geo_type` = '{$geo_type}'";
- $condition_time_value = filter_integers('t.`time_value`', $time_values);
-
- if ($geo_values === '*') {
- // the wildcard query should return data for all locations in `geo_type`
- $condition_geo_value = 'TRUE';
- } else if (is_array($geo_values)) {
- // return data for multiple location
- $condition_geo_value = filter_strings('t.`geo_value`', $geo_values);
- } else {
- // return data for a particular location
- $geo_escaped_value = mysqli_real_escape_string($dbh, $geo_values);
- $condition_geo_value = "t.`geo_value` = '{$geo_escaped_value}'";
- }
- $conditions = "({$condition_source}) AND ({$condition_signal}) AND ({$condition_sensor_name}) AND ({$condition_time_type}) AND ({$condition_geo_type}) AND ({$condition_time_value}) AND ({$condition_geo_value})";
-
- $subquery = "";
- if ($issues !== null) {
- //build the issue filter
- $condition_issue = filter_integers('t.`issue`', $issues);
- $query = "SELECT {$fields} FROM {$table} {$subquery} WHERE {$conditions} AND ({$condition_issue}) ORDER BY {$order}";
- } else if ($lag !== null) {
- //build the lag filter
- $condition_lag = "(t.`lag` = {$lag})";
- $query = "SELECT {$fields} FROM {$table} {$subquery} WHERE {$conditions} AND ({$condition_lag}) ORDER BY {$order}";
- } else if ($as_of !== null) {
- // fetch most recent issues with as of
- $sub_condition_asof = "(`issue` <= {$as_of})";
- $sub_fields = "max(`issue`) `max_issue`, `time_type`, `time_value`, `source`, `signal`, `geo_type`, `geo_value`";
- $sub_group = "`time_type`, `time_value`, `source`, `signal`, `geo_type`, `geo_value`";
- $sub_condition = "x.`max_issue` = t.`issue` AND x.`time_type` = t.`time_type` AND x.`time_value` = t.`time_value` AND x.`source` = t.`source` AND x.`signal` = t.`signal` AND x.`geo_type` = t.`geo_type` AND x.`geo_value` = t.`geo_value`";
- $subquery = "JOIN (SELECT {$sub_fields} FROM {$table} WHERE ({$conditions} AND {$sub_condition_asof}) GROUP BY {$sub_group}) x ON {$sub_condition}";
- $condition_version = 'TRUE';
- $query = "SELECT {$fields} FROM {$table} {$subquery} WHERE {$conditions} AND ({$condition_version}) ORDER BY {$order}";
- } else {
- // fetch most recent issue fast
- $query = "WITH t as (SELECT {$fields}, ROW_NUMBER() OVER (PARTITION BY t.`time_type`, t.`time_value`, t.`source`, t.`signal`, t.`geo_type`, t.`geo_value` ORDER BY t.`issue` DESC) row FROM {$table} {$subquery} WHERE {$conditions}) SELECT {$fields} FROM t where row = 1 ORDER BY {$order}";
- }
- // get the data from the database
- $epidata = array();
- execute_query($query, $epidata, $fields_string, $fields_int, $fields_float);
- // return the data
- return count($epidata) === 0 ? null : $epidata;
-}
-
-
-// all responses will have a result field
-$data = array('result' => -1);
-// connect to the database
-if(database_connect()) {
-
- // select the data source
- // endpoint parameter with a fallback to source parameter for compatibility reasons
- $endpoint = isset($_REQUEST['endpoint']) ? strtolower($_REQUEST['endpoint']) : (isset($_REQUEST['source']) ? strtolower($_REQUEST['source']) : null);
-
- if($endpoint === 'fluview') {
- if(require_all($data, array('epiweeks', 'regions'))) {
- // parse the request
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- $regions = extract_values($_REQUEST['regions'], 'str');
- $issues = isset($_REQUEST['issues']) ? extract_values($_REQUEST['issues'], 'int') : null;
- $lag = isset($_REQUEST['lag']) ? intval($_REQUEST['lag']) : null;
- $authorized = isset($_REQUEST['auth']) && $_REQUEST['auth'] === $AUTH['fluview'];
- // get the data
- $epidata = get_fluview($epiweeks, $regions, $issues, $lag, $authorized);
- store_result($data, $epidata);
- }
- } else if($endpoint === 'fluview_meta') {
- // get the data
- $epidata = meta_fluview();
- store_result($data, $epidata);
- } else if ($endpoint === 'fluview_clinical') {
- if(require_all($data, array('epiweeks', 'regions'))) {
- // parse the request
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- $regions = extract_values($_REQUEST['regions'], 'str');
- $issues = isset($_REQUEST['issues']) ? extract_values($_REQUEST['issues'], 'int') : null;
- $lag = isset($_REQUEST['lag']) ? intval($_REQUEST['lag']) : null;
- // get the data
- $epidata = get_fluview_clinical($epiweeks, $regions, $issues, $lag);
- store_result($data, $epidata);
- }
- } else if($endpoint === 'flusurv') {
- if(require_all($data, array('epiweeks', 'locations'))) {
- // parse the request
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- $locations = extract_values($_REQUEST['locations'], 'str');
- $issues = isset($_REQUEST['issues']) ? extract_values($_REQUEST['issues'], 'int') : null;
- $lag = isset($_REQUEST['lag']) ? intval($_REQUEST['lag']) : null;
- // get the data
- $epidata = get_flusurv($epiweeks, $locations, $issues, $lag);
- store_result($data, $epidata);
- }
- } else if ($endpoint === 'paho_dengue') {
- if(require_all($data, array('epiweeks', 'regions'))) {
- // parse the request
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- $regions = extract_values($_REQUEST['regions'], 'str');
- $issues = isset($_REQUEST['issues']) ? extract_values($_REQUEST['issues'], 'int') : null;
- $lag = isset($_REQUEST['lag']) ? intval($_REQUEST['lag']) : null;
- // get the data
- $epidata = get_paho_dengue($epiweeks, $regions, $issues, $lag);
- store_result($data, $epidata);
- }
- } else if ($endpoint === 'ecdc_ili') {
- if(require_all($data, array('epiweeks', 'regions'))) {
- // parse the request
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- $regions = extract_values($_REQUEST['regions'], 'str');
- $issues = isset($_REQUEST['issues']) ? extract_values($_REQUEST['issues'], 'int') : null;
- $lag = isset($_REQUEST['lag']) ? intval($_REQUEST['lag']) : null;
- // get the data
- $epidata = get_ecdc_ili($epiweeks, $regions, $issues, $lag);
- store_result($data, $epidata);
- }
- } else if ($endpoint === 'kcdc_ili') {
- if(require_all($data, array('epiweeks', 'regions'))) {
- // parse the request
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- $regions = extract_values($_REQUEST['regions'], 'str');
- $issues = isset($_REQUEST['issues']) ? extract_values($_REQUEST['issues'], 'int') : null;
- $lag = isset($_REQUEST['lag']) ? intval($_REQUEST['lag']) : null;
- // get the data
- $epidata = get_kcdc_ili($epiweeks, $regions, $issues, $lag);
- store_result($data, $epidata);
- }
- } else if($endpoint === 'ilinet' || $endpoint === 'stateili') {
- // these two sources are now combined into fluview
- $data['message'] = 'use fluview instead';
- } else if($endpoint === 'gft') {
- if(require_all($data, array('epiweeks', 'locations'))) {
- // parse the request
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- $locations = extract_values($_REQUEST['locations'], 'str');
- // get the data
- $epidata = get_gft($epiweeks, $locations);
- store_result($data, $epidata);
- }
- } else if($endpoint === 'ght') {
- if(require_all($data, array('auth', 'epiweeks', 'locations', 'query'))) {
- if($_REQUEST['auth'] === $AUTH['ght']) {
- // parse the request
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- $locations = extract_values($_REQUEST['locations'], 'str');
- $query = $_REQUEST['query'];
- // get the data
- $epidata = get_ght($epiweeks, $locations, $query);
- store_result($data, $epidata);
- } else {
- $data['message'] = 'unauthenticated';
- }
- }
- } else if($endpoint === 'twitter') {
- if(require_all($data, array('auth', 'locations'))) {
- if($_REQUEST['auth'] === $AUTH['twitter']) {
- // parse the request
- $locations = extract_values($_REQUEST['locations'], 'str');
- if(require_any($data, array('dates', 'epiweeks'))) {
- if(isset($_REQUEST['dates'])) {
- $resolution = 'daily';
- $dates = extract_values($_REQUEST['dates'], 'int');
- } else {
- $resolution = 'weekly';
- $dates = extract_values($_REQUEST['epiweeks'], 'int');
- }
- // get the data
- $epidata = get_twitter($locations, $dates, $resolution);
- store_result($data, $epidata);
- }
- } else {
- $data['message'] = 'unauthenticated';
- }
- }
- } else if($endpoint === 'wiki') {
- if(require_all($data, array('articles', 'language'))) {
- // parse the request
- $articles = extract_values($_REQUEST['articles'], 'str');
- $language = $_REQUEST['language'];
- if(require_any($data, array('dates', 'epiweeks'))) {
- if(isset($_REQUEST['dates'])) {
- $resolution = 'daily';
- $dates = extract_values($_REQUEST['dates'], 'int');
- } else {
- $resolution = 'weekly';
- $dates = extract_values($_REQUEST['epiweeks'], 'int');
- }
- $hours = isset($_REQUEST['hours']) ? extract_values($_REQUEST['hours'], 'int') : null;
- // get the data
- $epidata = get_wiki($articles, $language, $dates, $resolution, $hours);
- store_result($data, $epidata);
- }
- }
- } else if($endpoint === 'quidel') {
- if(require_all($data, array('auth', 'locations', 'epiweeks'))) {
- if($_REQUEST['auth'] === $AUTH['quidel']) {
- // parse the request
- $locations = extract_values($_REQUEST['locations'], 'str');
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- // get the data
- $epidata = get_quidel($locations, $epiweeks);
- store_result($data, $epidata);
- } else {
- $data['message'] = 'unauthenticated';
- }
- }
- } else if($endpoint === 'norostat') {
- if(require_all($data, array('auth', 'location', 'epiweeks'))) {
- if($_REQUEST['auth'] === $AUTH['norostat']) {
- // parse the request
- $location = $_REQUEST['location'];
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- // get the data
- $epidata = get_norostat($location, $epiweeks);
- store_result($data, $epidata);
- } else {
- $data['message'] = 'unauthenticated';
- }
- }
- } else if($endpoint === 'afhsb') {
- if(require_all($data, array('auth', 'locations', 'epiweeks', 'flu_types'))) {
- if($_REQUEST['auth'] === $AUTH['afhsb']) {
- // parse the request
- $locations = extract_values($_REQUEST['locations'], 'str');
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- $flu_types = extract_values($_REQUEST['flu_types'], 'str');
- // get the data
- $epidata = get_afhsb($locations, $epiweeks, $flu_types);
- store_result($data, $epidata);
- } else {
- $data['message'] = 'unauthenticated';
- }
- }
- } else if($endpoint === 'nidss_flu') {
- if(require_all($data, array('epiweeks', 'regions'))) {
- // parse the request
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- $regions = extract_values($_REQUEST['regions'], 'str');
- $issues = isset($_REQUEST['issues']) ? extract_values($_REQUEST['issues'], 'int') : null;
- $lag = isset($_REQUEST['lag']) ? intval($_REQUEST['lag']) : null;
- // get the data
- $epidata = get_nidss_flu($epiweeks, $regions, $issues, $lag);
- store_result($data, $epidata);
- }
- } else if($endpoint === 'nidss_dengue') {
- if(require_all($data, array('epiweeks', 'locations'))) {
- // parse the request
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- $locations = extract_values($_REQUEST['locations'], 'str');
- // get the data
- $epidata = get_nidss_dengue($epiweeks, $locations);
- store_result($data, $epidata);
- }
- } else if($endpoint === 'delphi') {
- if(require_all($data, array('system', 'epiweek'))) {
- // parse the request
- $system = $_REQUEST['system'];
- $epiweek = intval($_REQUEST['epiweek']);
- // get the data
- $epidata = get_forecast($system, $epiweek);
- store_result($data, $epidata);
- }
- } else if($endpoint === 'signals') {
- // this sources is now replaced by sensors
- $data['message'] = 'use sensors instead';
- } else if($endpoint === 'cdc') {
- if(require_all($data, array('auth', 'epiweeks', 'locations'))) {
- if($_REQUEST['auth'] === $AUTH['cdc']) {
- // parse the request
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- $locations = extract_values($_REQUEST['locations'], 'str');
- // get the data
- $epidata = get_cdc($epiweeks, $locations);
- store_result($data, $epidata);
- } else {
- $data['message'] = 'unauthenticated';
- }
- }
- } else if($endpoint === 'sensors') {
- if(require_all($data, array('names', 'locations', 'epiweeks'))) {
- if(!array_key_exists('auth', $_REQUEST)) {
- $auth_tokens_presented = array();
- } else {
- $auth_tokens_presented = extract_values($_REQUEST['auth'], 'str');
- }
- $names = extract_values($_REQUEST['names'], 'str');
- $n_names = count($names);
- $n_auth_tokens_presented = count($auth_tokens_presented);
- $max_valid_granular_tokens_per_name = max(array_map('count', $GRANULAR_SENSOR_AUTH_TOKENS));
- // The number of valid granular tokens is related to the number of auth token checks that a single query could perform. Use the max number of valid granular auth tokens per name in the check below as a way to prevent leakage of sensor names (but revealing the number of sensor names) via this interface. Treat all sensors as non-open for convenience of calculation.
- if($n_names === 0) {
- // Check whether no names were provided to prevent edge-case issues in error message below, and in case surrounding behavior changes in the future:
- $data['message'] = 'no sensor names provided';
- } else if($n_auth_tokens_presented > 1) {
- $data['message'] = 'currently, only a single auth token is allowed to be presented at a time; please issue a separate query for each sensor name using only the corresponding token';
- } else if(
- // Check whether max number of presented-vs.-acceptable token comparisons that would be performed is over the set limits, avoiding calculation of numbers > PHP_INT_MAX/100:
- // Global auth token comparison limit check:
- $n_auth_tokens_presented > $MAX_GLOBAL_AUTH_CHECKS_PER_SENSOR_QUERY ||
- // Granular auth token comparison limit check:
- $n_names > (int)((PHP_INT_MAX/100-1)/max(1,$max_valid_granular_tokens_per_name)) ||
- $n_auth_tokens_presented > (int)(PHP_INT_MAX/100/max(1,$n_names*$max_valid_granular_tokens_per_name)) ||
- $n_auth_tokens_presented * $n_names * $max_valid_granular_tokens_per_name > $MAX_GRANULAR_AUTH_CHECKS_PER_SENSOR_QUERY
- ) {
- $data['message'] = 'too many sensors requested and/or auth tokens presented; please divide sensors into batches and/or use only the tokens needed for the sensors requested';
- } else if(count($auth_tokens_presented) > $MAX_AUTH_KEYS_PROVIDED_PER_SENSOR_QUERY) {
- // this check should be redundant with >1 check as well as global check above
- $data['message'] = 'too many auth tokens presented';
- } else {
- $unauthenticated_or_nonexistent_sensors = array();
- foreach($names as $name) {
- $sensor_is_open = in_array($name, $OPEN_SENSORS);
- // test whether they provided the "global" auth token that works for all sensors:
- $sensor_authenticated_globally = in_array($AUTH['sensors'], $auth_tokens_presented);
- // test whether they provided a "granular" auth token for one of the
- // sensor_subsets containing this sensor (if any):
- $sensor_authenticated_granularly = false;
- if(array_key_exists($name, $GRANULAR_SENSOR_AUTH_TOKENS)) {
- $acceptable_granular_tokens_for_sensor = $GRANULAR_SENSOR_AUTH_TOKENS[$name];
- // check for nonempty intersection between provided and acceptable
- // granular auth tokens:
- foreach($acceptable_granular_tokens_for_sensor as $acceptable_granular_token) {
- if(in_array($acceptable_granular_token, $auth_tokens_presented)) {
- $sensor_authenticated_granularly = true;
- break;
- }
- }
- } // (else: there are no granular tokens for this sensor; can't authenticate granularly)
- if(! $sensor_is_open &&
- ! $sensor_authenticated_globally &&
- ! $sensor_authenticated_granularly) {
- // authentication failed for this sensor; append to list:
- array_push($unauthenticated_or_nonexistent_sensors, $name);
- }
- }
- if (!empty($unauthenticated_or_nonexistent_sensors)) {
- $data['message'] = 'unauthenticated/nonexistent sensor(s): ' . implode(',', $unauthenticated_or_nonexistent_sensors);
- // // Alternative message that may enable shorter tokens:
- // $data['message'] = 'some/all sensors requested were unauthenticated/nonexistent';
- } else {
- // parse the request
- $locations = extract_values($_REQUEST['locations'], 'str');
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- // get the data
- $epidata = get_sensors($names, $locations, $epiweeks);
- store_result($data, $epidata);
- }
- }
- }
- } else if($endpoint === 'dengue_sensors') {
- if(require_all($data, array('auth', 'names', 'locations', 'epiweeks'))) {
- if($_REQUEST['auth'] === $AUTH['sensors']) {
- // parse the request
- $names = extract_values($_REQUEST['names'], 'str');
- $locations = extract_values($_REQUEST['locations'], 'str');
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- // get the data
- $epidata = get_dengue_sensors($names, $locations, $epiweeks);
- store_result($data, $epidata);
- } else {
- $data['message'] = 'unauthenticated';
- }
- }
- } else if($endpoint === 'nowcast') {
- if(require_all($data, array('locations', 'epiweeks'))) {
- // parse the request
- $locations = extract_values($_REQUEST['locations'], 'str');
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- // get the data
- $epidata = get_nowcast($locations, $epiweeks);
- store_result($data, $epidata);
- }
- } else if($endpoint === 'dengue_nowcast') {
- if(require_all($data, array('locations', 'epiweeks'))) {
- // parse the request
- $locations = extract_values($_REQUEST['locations'], 'str');
- $epiweeks = extract_values($_REQUEST['epiweeks'], 'int');
- // get the data
- $epidata = get_dengue_nowcast($locations, $epiweeks);
- store_result($data, $epidata);
- }
- } else if($endpoint === 'meta') {
- // get the data
- $epidata = get_meta();
- store_result($data, $epidata);
- } else if($endpoint === 'meta_norostat') {
- if(require_all($data, array('auth'))) {
- if($_REQUEST['auth'] === $AUTH['norostat']) {
- $epidata = get_meta_norostat();
- store_result($data, $epidata);
- } else {
- $data['message'] = 'unauthenticated';
- }
- }
- } else if($endpoint === 'meta_afhsb') {
- if(require_all($data, array('auth'))) {
- if($_REQUEST['auth'] === $AUTH['afhsb']) {
- $epidata = get_meta_afhsb();
- store_result($data, $epidata);
- } else {
- $data['message'] = 'unauthenticated';
- }
- }
- } else if($endpoint === 'covidcast') {
- if(require_all($data, array('data_source', 'time_type', 'geo_type', 'time_values'))
- && require_any($data, array('signal', 'signals'))
- && require_any($data, array('geo_value', 'geo_values'))) {
- // parse the request
- $time_values = extract_dates($_REQUEST['time_values']);
- $as_of = isset($_REQUEST['as_of']) ? parse_date($_REQUEST['as_of']) : null;
- $issues = isset($_REQUEST['issues']) ? extract_dates($_REQUEST['issues']) : null;
- $lag = isset($_REQUEST['lag']) ? intval($_REQUEST['lag']) : null;
- $signals = extract_values(isset($_REQUEST['signals']) ? $_REQUEST['signals'] : $_REQUEST['signal'], 'string');
- $geo_values = isset($_REQUEST['geo_value']) ? $_REQUEST['geo_value'] : extract_values($_REQUEST['geo_values'], 'string');
- // get the data
- $epidata = get_covidcast(
- $_REQUEST['data_source'],
- $signals,
- $_REQUEST['time_type'],
- $_REQUEST['geo_type'],
- $time_values,
- $geo_values,
- $as_of,
- $issues,
- $lag);
- if(isset($_REQUEST['format']) && $_REQUEST['format']=="tree") {
- //organize results by signal
- $epi_tree = array();
- $key = -1;
- foreach ($epidata as $row) {
- if ($key != $row['signal']) {
- $key = $row['signal'];
- $epi_tree[$key] = array();
- }
- unset($row['signal']);
- array_push($epi_tree[$key],$row);
- }
- $epidata = array($epi_tree);
- }
- store_result($data, $epidata);
- }
- } else if($endpoint === 'covidcast_meta') {
- // get the metadata
- $epidata = get_covidcast_meta();
- store_result($data, $epidata);
- } else if($endpoint === 'signal_dashboard_status') {
- $signal_dash_data = get_signal_dash_status_data();
- store_result($data, $signal_dash_data);
- } else if($endpoint === 'signal_dashboard_coverage') {
- $signal_dash_data = get_signal_dash_coverage_data();
- store_result($data, $signal_dash_data);
- } else if($endpoint === 'covid_hosp' || $source === 'covid_hosp_state_timeseries') {
- if(require_all($data, array('states', 'dates'))) {
- // parse the request
- $states = extract_values($_REQUEST['states'], 'str');
- $dates = extract_values($_REQUEST['dates'], 'int');
- $issues = isset($_REQUEST['issues']) ? extract_values($_REQUEST['issues'], 'int') : null;
- // get the data
- $epidata = get_covid_hosp_state_timeseries($states, $dates, $issues);
- store_result($data, $epidata);
- }
- } else if($endpoint === 'covid_hosp_facility') {
- if(require_all($data, array('hospital_pks', 'collection_weeks'))) {
- // parse the request
- $hospital_pks = extract_values($_REQUEST['hospital_pks'], 'str');
- $collection_weeks = extract_values($_REQUEST['collection_weeks'], 'int');
- $publication_dates = isset($_REQUEST['publication_dates']) ? extract_values($_REQUEST['publication_dates'], 'int') : null;
- // get the data
- $epidata = get_covid_hosp_facility($hospital_pks, $collection_weeks, $publication_dates);
- store_result($data, $epidata);
- }
- } else if($endpoint === 'covid_hosp_facility_lookup') {
- if(require_any($data, array('state', 'ccn', 'city', 'zip', 'fips_code'))) {
- $state = isset($_REQUEST['state']) ? extract_values($_REQUEST['state'], 'str') : null;
- $ccn = isset($_REQUEST['ccn']) ? extract_values($_REQUEST['ccn'], 'str') : null;
- $city = isset($_REQUEST['city']) ? extract_values($_REQUEST['city'], 'str') : null;
- $zip = isset($_REQUEST['zip']) ? extract_values($_REQUEST['zip'], 'str') : null;
- $fips_code = isset($_REQUEST['fips_code']) ? extract_values($_REQUEST['fips_code'], 'str') : null;
- // get the data
- $epidata = get_covid_hosp_facility_lookup($state, $ccn, $city, $zip, $fips_code);
- store_result($data, $epidata);
- }
- } else if($endpoint === 'covidcast_nowcast') {
- if(require_all($data, array('data_source', 'time_type', 'geo_type', 'time_values', 'signals', 'sensor_names'))
- && require_any($data, array('geo_value', 'geo_values'))) {
- // parse the request
- $time_values = extract_dates($_REQUEST['time_values']);
- $as_of = isset($_REQUEST['as_of']) ? parse_date($_REQUEST['as_of']) : null;
- $issues = isset($_REQUEST['issues']) ? extract_dates($_REQUEST['issues']) : null;
- $lag = isset($_REQUEST['lag']) ? intval($_REQUEST['lag']) : null;
- $signals = extract_values(isset($_REQUEST['signals']) ? $_REQUEST['signals'] : $_REQUEST['signal'], 'string');
- $sensor_names = extract_values(isset($_REQUEST['sensor_names']) ? $_REQUEST['sensor_names'] : $_REQUEST['sensor_names'], 'sensor_names');
- $geo_values = isset($_REQUEST['geo_value']) ? $_REQUEST['geo_value'] : extract_values($_REQUEST['geo_values'], 'string');
- // get the data
- $epidata = get_covidcast_nowcast(
- $_REQUEST['data_source'],
- $signals,
- $sensor_names,
- $_REQUEST['time_type'],
- $_REQUEST['geo_type'],
- $time_values,
- $geo_values,
- $as_of,
- $issues,
- $lag);
- store_result($data, $epidata);
- }
- } else {
- $data['message'] = 'no data source specified';
- }
- // API analytics
- record_analytics($endpoint, $data);
-} else {
- $data['message'] = 'database error';
-}
-
-if(isset($_REQUEST['format']) && $_REQUEST['format'] == "csv") {
- send_csv($data);
-} else if(isset($_REQUEST['format']) && $_REQUEST['format'] == "json") {
- send_json($data);
-} else {
- // send the response as a json object
- header('Content-Type: application/json');
- echo json_encode($data);
-}
-?>
diff --git a/src/server/api_helpers.php b/src/server/api_helpers.php
deleted file mode 100644
index 076033801..000000000
--- a/src/server/api_helpers.php
+++ /dev/null
@@ -1,420 +0,0 @@
- $first) {
- // add the range as an array
- array_push($values, array($first, $last));
- } else {
- // the range is inverted, this is an error
- return null;
- }
- } else {
- // this is a single value
- if($type === 'int') {
- // cast to integer
- $value = intval($part);
- } else {
- // interpret the string literally
- $value = $part;
- }
- // add the extracted value to the list
- array_push($values, $value);
- }
- }
- // success, return the list
- return $values;
-}
-
-/**
- * parses a given string in format YYYYMMDD or YYYY-MM-DD to a number in the form YYYYMMDD
- */
-function parse_date($s) {
- return intval(str_replace('-', '', $s));
-}
-
-// extracts an array of values and/or ranges from a string
-// $str: the string to parse
-function extract_dates($str) {
- if($str === null || strlen($str) === 0) {
- // nothing to do
- return null;
- }
- $values = array();
- // split on commas and loop over each entry, which could be either a single value or a range of values
- $parts = explode(',', $str);
-
- $push_range = function($first, $last) {
- $first = parse_date($first);
- $last = parse_date($last);
- if($last === $first) {
- // the first and last numbers are the same, just treat it as a singe value
- return $first;
- }
- if($last > $first) {
- // add the range as an array
- return array($first, $last);
- }
- // the range is inverted, this is an error
- return false;
- };
-
- foreach($parts as $part) {
- if(strpos($part, '-') === false && strpos($part, ':') === false) {
- // YYYYMMDD
- array_push($values, parse_date($part));
- continue;
- }
- if (strpos($part, ':') !== false) {
- // YYYY-MM-DD:YYYY-MM-DD
- $range = explode(':', $part);
- $r = $push_range($range[0], $range[1]);
- if ($r === false) {
- return null;
- }
- array_push($values, $r);
- }
- // YYYY-MM-DD or YYYYMMDD-YYYYMMDD
- // split on the dash
- $range = explode('-', $part);
- if (count($range) === 2) {
- // YYYYMMDD-YYYYMMDD
- $r = $push_range($range[0], $range[1]);
- if ($r === false) {
- return null;
- }
- array_push($values, $r);
- continue;
- }
- // YYYY-MM-DD
- array_push($values, parse_date($part));
- }
- // success, return the list
- return $values;
-}
-
-// give a comma-separated, quoted list of states in an HHS or Census region
-function get_region_states($region) {
- switch($region) {
- case 'hhs1': return "'VT', 'CT', 'ME', 'MA', 'NH', 'RI'";
- case 'hhs2': return "'NJ', 'NY'";
- case 'hhs3': return "'DE', 'DC', 'MD', 'PA', 'VA', 'WV'";
- case 'hhs4': return "'AL', 'FL', 'GA', 'KY', 'MS', 'NC', 'TN', 'SC'";
- case 'hhs5': return "'IL', 'IN', 'MI', 'MN', 'OH', 'WI'";
- case 'hhs6': return "'AR', 'LA', 'NM', 'OK', 'TX'";
- case 'hhs7': return "'IA', 'KS', 'MO', 'NE'";
- case 'hhs8': return "'CO', 'MT', 'ND', 'SD', 'UT', 'WY'";
- case 'hhs9': return "'AZ', 'CA', 'HI', 'NV'";
- case 'hhs10': return "'AK', 'ID', 'OR', 'WA'";
- case 'cen1': return "'CT', 'ME', 'MA', 'NH', 'RI', 'VT'";
- case 'cen2': return "'NJ', 'NY', 'PA'";
- case 'cen3': return "'IL', 'IN', 'MI', 'OH', 'WI'";
- case 'cen4': return "'IA', 'KS', 'MN', 'MO', 'NE', 'ND', 'SD'";
- case 'cen5': return "'DE', 'DC', 'FL', 'GA', 'MD', 'NC', 'SC', 'VA', 'WV'";
- case 'cen6': return "'AL', 'KY', 'MS', 'TN'";
- case 'cen7': return "'AR', 'LA', 'OK', 'TX'";
- case 'cen8': return "'AZ', 'CO', 'ID', 'MT', 'NV', 'NM', 'UT', 'WY'";
- case 'cen9': return "'AK', 'CA', 'HI', 'OR', 'WA'";
- }
- return null;
-}
-
-function record_analytics($source, $data) {
- global $dbh;
- $ip = mysqli_real_escape_string($dbh, isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '');
- $ua = mysqli_real_escape_string($dbh, isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '');
- $source = mysqli_real_escape_string($dbh, isset($source) ? $source : '');
- $result = intval($data['result']);
- $num_rows = intval(isset($data['epidata']) ? count($data['epidata']) : 0);
- mysqli_query($dbh, "INSERT INTO `api_analytics` (`datetime`, `ip`, `ua`, `source`, `result`, `num_rows`) VALUES (now(), '{$ip}', '{$ua}', '{$source}', {$result}, {$num_rows})");
-}
-
-function send_status(&$data) {
- if (intval($data["result"]) > 0 || intval($data["result"]) == -2) {
- return FALSE;
- }
- if ($data["message"] == 'database error') {
- http_response_code(500);
- } else if ($data["message"] == 'unauthenticated') {
- http_response_code(401);
- } else {
- http_response_code(400); // bad request
- }
- header('Content-Type: application/json');
- echo json_encode($data);
- return TRUE;
-}
-
-function send_csv(&$data) {
- if (send_status($data)) {
- return;
- }
- header('Content-Type: text/csv');
- header('Content-Disposition: attachment; filename=epidata.csv');
-
- if (intval($data["result"]) == -2) {
- // empty
- return;
- }
-
- $rows = $data["epidata"];
- $headers = array_keys($rows[0]);
- $out = fopen('php://output', 'w');
- fputcsv($out, $headers);
- foreach ($rows as $row) {
- fputcsv($out, $row);
- }
- fclose($out);
-}
-
-function send_json(&$data) {
- if (send_status($data)) {
- return;
- }
- header('Content-Type: application/json');
-
- if (intval($data["result"]) == -2) {
- echo json_encode(array());
- } else {
- echo json_encode($data["epidata"]);
- }
-}
-
-?>
diff --git a/src/server/database_config.php b/src/server/database_config.php
deleted file mode 100644
index 1667f134d..000000000
--- a/src/server/database_config.php
+++ /dev/null
@@ -1,7 +0,0 @@
- 'delphi_database_epidata',
- 'port' => 3306,
-);
-?>