payfrit-api/api/businesses/list.php
John Mizerek 1f81d98c52 Initial PHP API migration from CFML
Complete port of all 163 API endpoints from Lucee/CFML to PHP 8.3.
Shared helpers in api/helpers.php (DB, auth, request/response, security).
PDO prepared statements throughout. Same JSON response shapes as CFML.
2026-03-14 14:26:59 -07:00

83 lines
2.6 KiB
PHP

<?php
require_once __DIR__ . '/../helpers.php';
runAuth();
/**
* List Businesses
* POST: { lat?: float, lng?: float }
* Returns nearest 50 businesses sorted by distance.
*/
function haversineDistance(float $lat1, float $lng1, float $lat2, float $lng2): float {
$R = 3959; // Earth radius in miles
$dLat = deg2rad($lat2 - $lat1);
$dLng = deg2rad($lng2 - $lng1);
$a = sin($dLat / 2) ** 2 +
cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
sin($dLng / 2) ** 2;
$a = max(0, min(1, $a));
$c = 2 * asin(sqrt($a));
return $R * $c;
}
try {
$data = readJsonBody();
$userLat = (float) ($data['lat'] ?? 0);
$userLng = (float) ($data['lng'] ?? 0);
$hasUserLocation = ($userLat != 0 && $userLng != 0);
$rows = queryTimed("
SELECT
b.ID, b.Name, b.ParentBusinessID,
(SELECT COUNT(*) FROM Businesses c WHERE c.ParentBusinessID = b.ID) AS ChildCount,
a.Latitude AS AddressLat, a.Longitude AS AddressLng,
a.City AS AddressCity, a.Line1 AS AddressLine1
FROM Businesses b
LEFT JOIN Addresses a ON b.AddressID = a.ID
WHERE (b.IsDemo = 0 OR b.IsDemo IS NULL)
AND (b.IsPrivate = 0 OR b.IsPrivate IS NULL)
AND (b.ParentBusinessID IS NULL OR b.ParentBusinessID = 0)
ORDER BY b.Name
");
$businesses = [];
foreach ($rows as $r) {
$bizLat = (float) ($r['AddressLat'] ?? 0);
$bizLng = (float) ($r['AddressLng'] ?? 0);
$distance = 99999;
if ($hasUserLocation && $bizLat != 0 && $bizLng != 0) {
$distance = haversineDistance($userLat, $userLng, $bizLat, $bizLng);
}
$businesses[] = [
'BusinessID' => (int) $r['ID'],
'Name' => $r['Name'],
'HasChildren' => ((int) $r['ChildCount']) > 0,
'City' => $r['AddressCity'] ?? '',
'Line1' => $r['AddressLine1'] ?? '',
'Latitude' => $bizLat,
'Longitude' => $bizLng,
'DistanceMiles' => $distance,
];
}
// Sort by distance if user location provided
if ($hasUserLocation) {
usort($businesses, fn($a, $b) => $a['DistanceMiles'] <=> $b['DistanceMiles']);
}
// Limit to 50
$businesses = array_slice($businesses, 0, 50);
jsonResponse([
'OK' => true,
'ERROR' => '',
'VERSION' => 'businesses_list_v5',
'BUSINESSES' => $businesses,
'Businesses' => $businesses,
]);
} catch (Exception $e) {
apiAbort(['OK' => false, 'ERROR' => 'server_error', 'DETAIL' => $e->getMessage()]);
}