684 lines
24 KiB
PHP
684 lines
24 KiB
PHP
<?php
|
|
require_once __DIR__ . '/common.php';
|
|
|
|
$dbconn = getDBConnection();
|
|
|
|
//no gets, current point outage info
|
|
if (empty(array_diff_key($_GET, array('service' => '')))) {
|
|
try {
|
|
$query = "
|
|
SELECT json_build_object(
|
|
'type', 'FeatureCollection',
|
|
'features', json_agg(
|
|
json_build_object(
|
|
'type', 'Feature',
|
|
'geometry', ST_AsGeoJSON(realgeom)::json,
|
|
'properties', json_build_object(
|
|
'time', startguess,
|
|
'county', county,
|
|
'state', state,
|
|
'outage', outagen,
|
|
'lastchange', lastchange,
|
|
'cause', cause,
|
|
'area_geometry', ST_AsGeoJSON(COALESCE(realareageom, realgeom))::json
|
|
)
|
|
)
|
|
ORDER BY startguess ASC
|
|
)
|
|
)
|
|
FROM power
|
|
WHERE cwa = $1 AND active = true
|
|
";
|
|
|
|
$result = pg_query_params($dbconn, $query, array('RLX'));
|
|
if ($result === false) {
|
|
throw new Exception('Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
// Check if we got results
|
|
if ($resultArray && isset($resultArray[0]['json_build_object'])) {
|
|
header('Content-Type: application/json');
|
|
echo $resultArray[0]['json_build_object'];
|
|
} else {
|
|
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
} catch (Exception $e) {
|
|
http_response_code(500);
|
|
die('Query execution failed: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['states'])) {
|
|
try {
|
|
$query = "
|
|
SELECT jsonb_build_object(
|
|
'type', 'FeatureCollection',
|
|
'features', jsonb_agg(features.feature)
|
|
)
|
|
FROM (
|
|
SELECT jsonb_build_object(
|
|
'type', 'Feature',
|
|
'geometry', ST_AsGeoJSON(ST_Transform(geom, 4326))::jsonb,
|
|
'properties', to_jsonb(properties) - 'geom'
|
|
) AS feature
|
|
FROM (
|
|
SELECT *
|
|
FROM states
|
|
WHERE state IN ('WV', 'VA', 'KY', 'MD', 'PA', 'OH')
|
|
) AS properties
|
|
) AS features
|
|
";
|
|
|
|
$result = pg_query($dbconn, $query);
|
|
if ($result === false) {
|
|
throw new Exception('Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
// Set proper JSON header and handle output
|
|
header('Content-Type: application/json');
|
|
if ($resultArray && isset($resultArray[0]['jsonb_build_object'])) {
|
|
echo $resultArray[0]['jsonb_build_object'];
|
|
} else {
|
|
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
} catch (Exception $e) {
|
|
http_response_code(500);
|
|
header('Content-Type: application/json');
|
|
echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['max'])) {
|
|
if (isset($_GET['start']) && isset($_GET['end'])) {
|
|
try {
|
|
$starttime = getParam('start');
|
|
$endtime = getParam('end');
|
|
|
|
$query = "
|
|
SELECT DISTINCT ON (county, state)
|
|
max(outage) as max_outage,
|
|
county,
|
|
state
|
|
FROM (
|
|
SELECT DISTINCT ON (county, state, update)
|
|
county,
|
|
state,
|
|
SUM(outages) as outage,
|
|
update as time,
|
|
SUM(served) as served
|
|
FROM countyoutages
|
|
WHERE update > $2
|
|
AND update < $3
|
|
AND cwa = $1
|
|
GROUP BY county, state, update
|
|
) as subquery
|
|
GROUP BY county, state
|
|
";
|
|
|
|
$result = pg_query_params(
|
|
$dbconn,
|
|
$query,
|
|
['RLX', $starttime, $endtime]
|
|
);
|
|
|
|
if ($result === false) {
|
|
throw new Exception('Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$results = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$results[] = $line;
|
|
}
|
|
|
|
header('Content-Type: application/json');
|
|
echo json_encode($results);
|
|
|
|
pg_free_result($result);
|
|
} catch (Exception $e) {
|
|
header('Content-Type: application/json');
|
|
http_response_code(500);
|
|
echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]);
|
|
exit;
|
|
}
|
|
} else {
|
|
header('Content-Type: application/json');
|
|
http_response_code(400);
|
|
echo json_encode(['error' => 'Both start and end parameters are required']);
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['county'])) {
|
|
try {
|
|
$query = "
|
|
WITH latest_update AS (
|
|
SELECT MAX(update) as max_update FROM countyoutages
|
|
)
|
|
SELECT
|
|
county,
|
|
state,
|
|
SUM(outages) as outage,
|
|
MAX(update) as time,
|
|
SUM(served) as served,
|
|
ROUND(
|
|
CASE
|
|
WHEN SUM(served) > 0 THEN (SUM(outages)::FLOAT / SUM(served)) * 100
|
|
ELSE 0
|
|
END::NUMERIC, 2
|
|
) as perout
|
|
FROM countyoutages
|
|
JOIN latest_update ON countyoutages.update = latest_update.max_update
|
|
WHERE cwa = $1
|
|
GROUP BY county, state
|
|
ORDER BY county, state;
|
|
";
|
|
|
|
$result = pg_query_params($dbconn, $query, ['RLX']);
|
|
if ($result === false) {
|
|
throw new Exception('Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$results = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$results[] = $line;
|
|
}
|
|
|
|
header('Content-Type: application/json');
|
|
echo json_encode($results);
|
|
|
|
pg_free_result($result);
|
|
} catch (Exception $e) {
|
|
header('Content-Type: application/json');
|
|
http_response_code(500);
|
|
echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['countyarchive'])) {
|
|
if (isset($_GET['start']) && isset($_GET['end'])) {
|
|
try {
|
|
$starttime = getParam('start');
|
|
$endtime = getParam('end');
|
|
|
|
$query = "
|
|
SELECT DISTINCT ON (county, state, update)
|
|
county,
|
|
state,
|
|
SUM(outages) as outage,
|
|
update as time,
|
|
SUM(served) as served
|
|
FROM countyoutages
|
|
WHERE update > $2
|
|
AND update < $3
|
|
AND cwa = $1
|
|
GROUP BY county, state, update
|
|
";
|
|
|
|
$result = pg_query_params($dbconn, $query, ['RLX', $starttime, $endtime]);
|
|
if ($result === false) {
|
|
throw new Exception('Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$results = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$results[] = $line;
|
|
}
|
|
|
|
header('Content-Type: application/json');
|
|
echo json_encode($results);
|
|
|
|
pg_free_result($result);
|
|
} catch (Exception $e) {
|
|
header('Content-Type: application/json');
|
|
http_response_code(500);
|
|
echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]);
|
|
if (isset($result)) {
|
|
pg_free_result($result);
|
|
}
|
|
exit;
|
|
}
|
|
} else {
|
|
header('Content-Type: application/json');
|
|
http_response_code(400);
|
|
echo json_encode(['error' => 'Both start and end parameters are required']);
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['archivepoint'])) {
|
|
try {
|
|
if (!isset($_GET['start']) || !isset($_GET['end'])) {
|
|
throw new Exception('Both start and end parameters are required');
|
|
}
|
|
|
|
$starttime = getParam('start');
|
|
$endtime = getParam('end');
|
|
|
|
$query = "
|
|
SELECT json_build_object(
|
|
'type', 'FeatureCollection',
|
|
'features', json_agg(
|
|
json_build_object(
|
|
'type', 'Feature',
|
|
'geometry', ST_AsGeoJSON(realgeom)::json,
|
|
'properties', json_build_object(
|
|
'time', startguess,
|
|
'county', county,
|
|
'state', state,
|
|
'outage', outagen,
|
|
'lastchange', lastchange,
|
|
'cause', cause
|
|
)
|
|
)
|
|
ORDER BY startguess ASC
|
|
)
|
|
)
|
|
FROM power
|
|
WHERE cwa = $1
|
|
AND startguess > $2
|
|
AND lastchange < $3
|
|
";
|
|
|
|
$result = pg_query_params($dbconn, $query, ['RLX', $starttime, $endtime]);
|
|
if ($result === false) {
|
|
throw new Exception('Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
header('Content-Type: application/json');
|
|
if ($resultArray && isset($resultArray[0]['json_build_object'])) {
|
|
echo $resultArray[0]['json_build_object'];
|
|
} else {
|
|
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
} catch (Exception $e) {
|
|
header('Content-Type: application/json');
|
|
$statusCode = strpos($e->getMessage(), 'required') !== false ? 400 : 500;
|
|
http_response_code($statusCode);
|
|
echo json_encode(['error' => $e->getMessage()]);
|
|
if (isset($result)) {
|
|
pg_free_result($result);
|
|
}
|
|
exit;
|
|
}
|
|
}
|
|
|
|
if(@$_GET['svr'] =='current') {
|
|
$result = pg_query($dbconn,
|
|
"SELECT json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type','Feature', 'geometry', ST_AsGeoJSON(nwspoly)::json,'properties',json_build_object('issue',issue,'end',endtime,'vtec',vtec,'type',warntype)))) FROM svr where issue < now() and endtime > now()") or die('Query failed: ' . pg_last_error());
|
|
$resultArray = pg_fetch_all($result);
|
|
echo($resultArray[0]['json_build_object']);
|
|
pg_free_result($result);
|
|
}
|
|
|
|
if (isset($_GET['svr']) && $_GET['svr'] === 'archive') {
|
|
try {
|
|
$result = null;
|
|
|
|
if (isset($_GET['start']) && isset($_GET['end'])) {
|
|
$starttime = getParam('start');
|
|
$endtime = getParam('end');
|
|
|
|
$query = "
|
|
SELECT json_build_object(
|
|
'type', 'FeatureCollection',
|
|
'features', json_agg(
|
|
json_build_object(
|
|
'type', 'Feature',
|
|
'geometry', ST_AsGeoJSON(nwspoly)::json,
|
|
'properties', json_build_object(
|
|
'issue', issue,
|
|
'end', endtime,
|
|
'vtec', vtec,
|
|
'type', warntype
|
|
)
|
|
)
|
|
)
|
|
)
|
|
FROM svr
|
|
WHERE issue > $1
|
|
AND endtime < $2
|
|
";
|
|
|
|
$result = pg_query_params($dbconn, $query, [$starttime, $endtime]);
|
|
} elseif (!isset($_GET['start']) && !isset($_GET['end'])) {
|
|
$query = "
|
|
SELECT json_build_object(
|
|
'type', 'FeatureCollection',
|
|
'features', json_agg(
|
|
json_build_object(
|
|
'type', 'Feature',
|
|
'geometry', ST_AsGeoJSON(nwspoly)::json,
|
|
'properties', json_build_object(
|
|
'issue', issue,
|
|
'end', endtime,
|
|
'vtec', vtec,
|
|
'type', warntype
|
|
)
|
|
)
|
|
)
|
|
)
|
|
FROM svr
|
|
WHERE issue < NOW() - INTERVAL '24 hours'
|
|
AND endtime > NOW() - INTERVAL '24 hours'
|
|
";
|
|
|
|
$result = pg_query($dbconn, $query);
|
|
} else {
|
|
throw new Exception('Both start and end parameters are required together');
|
|
}
|
|
|
|
if ($result === false) {
|
|
throw new Exception('Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
header('Content-Type: application/json');
|
|
if ($resultArray && isset($resultArray[0]['json_build_object'])) {
|
|
echo $resultArray[0]['json_build_object'];
|
|
} else {
|
|
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
} catch (Exception $e) {
|
|
if (isset($result)) {
|
|
pg_free_result($result);
|
|
}
|
|
header('Content-Type: application/json');
|
|
$statusCode = strpos($e->getMessage(), 'required') !== false ? 400 : 500;
|
|
http_response_code($statusCode);
|
|
echo json_encode(['error' => $e->getMessage()]);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['svrpolys'])) {
|
|
try {
|
|
$query = "
|
|
SELECT
|
|
vtec,
|
|
outagesvalid,
|
|
polygonpop,
|
|
outagesbuffer,
|
|
lsrids
|
|
FROM svr
|
|
WHERE EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - endtime)) / 60 / 60 / 24 < 60
|
|
";
|
|
|
|
$result = pg_query($dbconn, $query);
|
|
if ($result === false) {
|
|
throw new Exception('Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$results = [];
|
|
while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
|
|
$results[] = $line;
|
|
}
|
|
|
|
header('Content-Type: application/json');
|
|
echo json_encode($results);
|
|
|
|
pg_free_result($result);
|
|
} catch (Exception $e) {
|
|
if (isset($result)) {
|
|
pg_free_result($result);
|
|
}
|
|
header('Content-Type: application/json');
|
|
http_response_code(500);
|
|
echo json_encode(['error' => $e->getMessage()]);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['powerids'])) {
|
|
try {
|
|
$powerids = $_GET['powerids'];
|
|
|
|
// Validate input exists and isn't empty
|
|
if (empty($powerids)) {
|
|
throw new Exception('No power IDs provided');
|
|
}
|
|
|
|
// Convert comma-separated string to array and sanitize
|
|
$poweridArray = explode(',', $powerids);
|
|
$sanitizedIds = array_filter(array_map('intval', $poweridArray));
|
|
|
|
if (empty($sanitizedIds)) {
|
|
throw new Exception('Invalid power ID format');
|
|
}
|
|
|
|
// Prepare placeholders for the query
|
|
$placeholders = implode(',', array_map(function($i) { return '$' . $i; }, range(1, count($sanitizedIds))));
|
|
|
|
$query = "
|
|
SELECT
|
|
lat,
|
|
lon,
|
|
lastchange,
|
|
startguess,
|
|
peakoutage,
|
|
cause,
|
|
lsrtime,
|
|
lsrref,
|
|
(lsrtime AT TIME ZONE 'America/New_York')::timestamp as lsrlocal
|
|
FROM power
|
|
WHERE id IN ($placeholders)
|
|
";
|
|
|
|
$result = pg_query_params($dbconn, $query, $sanitizedIds);
|
|
if ($result === false) {
|
|
throw new Exception('Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$results = pg_fetch_all($result) ?: [];
|
|
|
|
header('Content-Type: application/json');
|
|
echo json_encode($results);
|
|
|
|
pg_free_result($result);
|
|
} catch (Exception $e) {
|
|
if (isset($result)) {
|
|
pg_free_result($result);
|
|
}
|
|
header('Content-Type: application/json');
|
|
$statusCode = strpos($e->getMessage(), 'Invalid') !== false ? 400 : 500;
|
|
http_response_code($statusCode);
|
|
echo json_encode(['error' => $e->getMessage()]);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['poweridsgeojson'])) {
|
|
try {
|
|
$powerids = $_GET['poweridsgeojson'];
|
|
|
|
if (empty($powerids)) {
|
|
throw new Exception('No power IDs provided');
|
|
}
|
|
|
|
// Convert and sanitize power IDs
|
|
$poweridArray = explode(',', $powerids);
|
|
$sanitizedIds = array_filter(array_map('intval', $poweridArray));
|
|
|
|
if (empty($sanitizedIds)) {
|
|
throw new Exception('Invalid power ID format');
|
|
}
|
|
|
|
// Prepare placeholders
|
|
$placeholders = implode(',', array_map(function($i) { return '$' . $i; }, range(1, count($sanitizedIds))));
|
|
|
|
$query = "
|
|
SELECT json_build_object(
|
|
'type', 'FeatureCollection',
|
|
'features', json_agg(
|
|
json_build_object(
|
|
'type', 'Feature',
|
|
'geometry', ST_AsGeoJSON(realgeom)::json,
|
|
'properties', json_build_object(
|
|
'id', id,
|
|
'time', (startguess AT TIME ZONE 'UTC')::timestamp,
|
|
'county', county,
|
|
'state', state,
|
|
'cause', cause,
|
|
'outage', peakoutage,
|
|
'lsrtime', (lsrtime AT TIME ZONE 'UTC')::timestamp
|
|
)
|
|
) ORDER BY startguess ASC
|
|
)
|
|
)
|
|
FROM power
|
|
WHERE id IN ($placeholders)
|
|
";
|
|
|
|
$result = pg_query_params($dbconn, $query, $sanitizedIds);
|
|
if ($result === false) {
|
|
throw new Exception('Query failed: ' . pg_last_error());
|
|
}
|
|
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
header('Content-Type: application/json');
|
|
if ($resultArray && isset($resultArray[0]['json_build_object'])) {
|
|
echo $resultArray[0]['json_build_object'];
|
|
} else {
|
|
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
} catch (Exception $e) {
|
|
if (isset($result)) {
|
|
pg_free_result($result);
|
|
}
|
|
header('Content-Type: application/json');
|
|
$statusCode = strpos($e->getMessage(), 'Invalid') !== false ? 400 : 500;
|
|
http_response_code($statusCode);
|
|
echo json_encode(['error' => $e->getMessage()]);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['polygongeojson'])) {
|
|
$result = null; // Initialize result to null for catch block safety
|
|
try {
|
|
$polygonGeoJsonString = $_GET['polygongeojson'];
|
|
|
|
if (empty($polygonGeoJsonString)) {
|
|
throw new Exception('No GeoJSON polygon provided', 400); // Use exception code for status
|
|
}
|
|
|
|
// 1. Validate if the input is valid JSON
|
|
// We decode here primarily to check JSON validity.
|
|
// We'll pass the *original string* to PostGIS's ST_GeomFromGeoJSON for robustness.
|
|
$polygonGeoJson = json_decode($polygonGeoJsonString);
|
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
throw new Exception('Invalid JSON format: ' . json_last_error_msg(), 400);
|
|
}
|
|
|
|
// 2. Optional: Basic structural validation (can rely on PostGIS for full validation)
|
|
if (!is_object($polygonGeoJson) || !isset($polygonGeoJson->type) || !in_array($polygonGeoJson->type, ['MultiPolygon', 'Polygon'])) {
|
|
// Allow both Polygon and MultiPolygon for flexibility? Or stick to MultiPolygon?
|
|
// Let's allow Polygon too, as ST_Within works with both.
|
|
// If you strictly need *only* MultiPolygon, change the check.
|
|
throw new Exception('Input GeoJSON must be of type Polygon or MultiPolygon.', 400);
|
|
}
|
|
if (!isset($polygonGeoJson->coordinates) || !is_array($polygonGeoJson->coordinates)) {
|
|
throw new Exception('Input GeoJSON must have a coordinates array.', 400);
|
|
}
|
|
|
|
// 3. Prepare the PostgreSQL Query using PostGIS functions
|
|
// - ST_GeomFromGeoJSON($1): Parses the input GeoJSON string.
|
|
// - ST_SetSRID(..., 4326): Assigns the WGS84 SRID (standard for GeoJSON). Adjust if your data uses a different SRID.
|
|
// - ST_Within(realgeom, ...): Checks if the power outage geometry is within the provided polygon geometry.
|
|
// - Ensure your 'realgeom' column has a spatial index for performance!
|
|
$query = "
|
|
SELECT json_build_object(
|
|
'type', 'FeatureCollection',
|
|
'features', json_agg(
|
|
json_build_object(
|
|
'type', 'Feature',
|
|
'geometry', ST_AsGeoJSON(realgeom)::json,
|
|
'properties', json_build_object(
|
|
'id', id,
|
|
'time', (startguess AT TIME ZONE 'UTC')::timestamp,
|
|
'county', county,
|
|
'state', state,
|
|
'cause', cause,
|
|
'outage', peakoutage,
|
|
'lsrtime', (lsrtime AT TIME ZONE 'UTC')::timestamp
|
|
)
|
|
) ORDER BY startguess ASC -- Optional ordering
|
|
)
|
|
)
|
|
FROM power
|
|
WHERE ST_Within(realgeom, ST_SetSRID(ST_GeomFromGeoJSON($1), 4326))
|
|
";
|
|
// Note: If 'realgeom' might be NULL, you might add "AND realgeom IS NOT NULL"
|
|
|
|
// 4. Execute the query with the GeoJSON string as a parameter
|
|
$params = [$polygonGeoJsonString];
|
|
$result = pg_query_params($dbconn, $query, $params);
|
|
|
|
if ($result === false) {
|
|
// Check for specific PostGIS errors related to invalid GeoJSON input
|
|
$pgError = pg_last_error($dbconn);
|
|
if (strpos($pgError, 'invalid GeoJSON representation') !== false || strpos($pgError, 'ParseException') !== false || strpos($pgError, 'Invalid polygon') !== false) {
|
|
throw new Exception('Invalid GeoJSON geometry data provided: ' . $pgError, 400);
|
|
} else {
|
|
// Throw a generic server error for other query failures
|
|
throw new Exception('Query failed: ' . $pgError, 500);
|
|
}
|
|
}
|
|
|
|
// 5. Fetch and Output Results
|
|
$resultArray = pg_fetch_all($result);
|
|
|
|
header('Content-Type: application/json');
|
|
if ($resultArray && isset($resultArray[0]['json_build_object'])) {
|
|
// Ensure null result from json_agg (no features found) returns empty array
|
|
$outputJson = $resultArray[0]['json_build_object'];
|
|
$outputData = json_decode($outputJson, true);
|
|
if (isset($outputData['features']) && $outputData['features'] === null) {
|
|
$outputData['features'] = [];
|
|
echo json_encode($outputData);
|
|
} else {
|
|
echo $outputJson; // Output the JSON directly from Postgres
|
|
}
|
|
} else {
|
|
// Should ideally be handled by the check above, but as a fallback
|
|
echo json_encode(['type' => 'FeatureCollection', 'features' => []]);
|
|
}
|
|
|
|
pg_free_result($result);
|
|
|
|
} catch (Exception $e) {
|
|
// 6. Error Handling
|
|
if (isset($result) && is_resource($result)) { // Check if $result is a valid resource before freeing
|
|
pg_free_result($result);
|
|
}
|
|
header('Content-Type: application/json');
|
|
// Use exception code for status if provided (>=400), default to 500
|
|
$statusCode = ($e->getCode() >= 400 && $e->getCode() < 600) ? $e->getCode() : 500;
|
|
http_response_code($statusCode);
|
|
echo json_encode(['error' => $e->getMessage()]);
|
|
exit; // Stop script execution after error
|
|
}
|
|
}
|
|
|
|
// Close database connection when needed
|
|
if (isset($dbconn)) {
|
|
pg_close($dbconn);
|
|
}
|
|
?>
|