em = $em; $this->gmaps_api_key = $gmaps_api_key; $this->cust_dist_limit = $cust_dist_limit; } protected function mapGetDistances(Point $point, $hubs) { $client = new GuzzleClient(); // origins $origins_value = $point->getLatitude() . ',' . $point->getLongitude(); // destinations $dests = []; foreach ($hubs as $hub) { $coord = $hub->getCoordinates(); $dests[] = round($coord->getLatitude(),5) . ',' . round($point->getLongitude(), 5); } $dests_value = implode('|', $dests); // google maps url $maps_url = self::URL_DISTANCE_MATRIX; // parameters $gmaps_params = [ 'origins' => $origins_value, 'destinations' => $dests_value, ]; //error_log(print_r($gmaps_params, true)); // query google maps api $res = $client->request('GET', $maps_url, [ 'query' => $gmaps_params, 'curl' => [ CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4 ], ]); return $res->getBody(); } public function getClosestHubs(Point $point, $limit, $time = false) { // get closest hubs based on st_distance function from db $query = $this->em->createQuery('SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h' . ($time ? ' WHERE :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist') ->setParameter('lat', $point->getLatitude()) ->setParameter('lng', $point->getLongitude()); if ($time) { $query->setParameter('time', $time); } $query->setMaxResults($limit); // error_log($query->getSql()); $result = $query->getResult(); $hubs = []; $final_data = []; foreach ($result as $row) { //error_log($row[0]->getName() . ' - ' . $row['dist']); $hubs[] = $row[0]; // get coordinates of hub $hub_coordinates = $row[0]->getCoordinates(); $cust_lat = $point->getLatitude(); $cust_lng = $point->getLongitude(); $hub_lat = $hub_coordinates->getLatitude(); $hub_lng = $hub_coordinates->getLongitude(); // get distance in kilometers from customer point to hub point $dist = $this->distance($cust_lat, $cust_lng, $hub_lat, $hub_lng); $final_data[] = [ 'hub' => $row[0], 'db_distance' => $row['dist'], 'distance' => $dist, 'duration' => 0, ]; } return $final_data; /* // get actual distance details with eta from google maps api $raw_res = $this->mapGetDistances($point, $hubs); $res = json_decode($raw_res, true); //error_log(print_r($res, true)); // check if status is ok if ($res['status'] != 'OK') { return $final_data; // error_log('status not ok'); } // check that the elements array is there if (!isset($res['rows'][0]['elements'])) { // error_log('no elements'); return $final_data; } foreach($res['rows'][0]['elements'] as $index => $gm_row) { // check status if (isset($gm_row['status']) && $gm_row['status'] != 'OK') { // error_log('element row status not ok'); continue; } // set distance if (isset($gm_row['distance']['value'])) $final_data[$index]['distance'] = $gm_row['distance']['value']; // set duration if (isset($gm_row['duration']['value'])) $final_data[$index]['duration'] = $gm_row['duration']['value']; } return $final_data; */ } // NOTE: only the API calls this public function getClosestOpenHubs(Point $point, $limit, $time = false) { // get closest hubs based on st_distance function from db $query = $this->em->createQuery('SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h' . ($time ? ' WHERE h.status_open = true AND :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist') ->setParameter('lat', $point->getLatitude()) ->setParameter('lng', $point->getLongitude()); if ($time) { $query->setParameter('time', $time); } $query->setMaxResults($limit); // error_log($query->getSql()); $result = $query->getResult(); $hubs = []; $final_data = []; foreach ($result as $row) { //error_log($row[0]->getName() . ' - ' . $row['dist']); $hubs[] = $row[0]; // get coordinates of hub $hub_coordinates = $row[0]->getCoordinates(); $cust_lat = $point->getLatitude(); $cust_lng = $point->getLongitude(); $hub_lat = $hub_coordinates->getLatitude(); $hub_lng = $hub_coordinates->getLongitude(); // get distance in kilometers from customer point to hub point $dist = $this->distance($cust_lat, $cust_lng, $hub_lat, $hub_lng); if ($dist < $this->cust_dist_limit) { $final_data[] = [ 'hub' => $row[0], 'db_distance' => $row['dist'], 'distance' => $dist, 'duration' => 0, ]; } } error_log('nearest open hubs count: ' . count($final_data)); return $final_data; } protected function distance($lat1, $lon1, $lat2, $lon2) { if (($lat1 == $lat2) && ($lon1 == $lon2)) return 0; $theta = $lon1 - $lon2; $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); $dist = acos($dist); $dist = rad2deg($dist); $miles = $dist * 60 * 1.1515; return round(($miles * 1.609344), 1); } }