Added Other AP
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
|
||||
RewriteEngine On
|
||||
RewriteBase /SAVVY/geofencearea/
|
||||
#RewriteBase /
|
||||
|
||||
#Checks to
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.*)$ index.php?/$1 [L]
|
||||
|
||||
</IfModule>
|
||||
|
||||
<IfModule !mod_rewrite.c>
|
||||
# If we don't have mod_rewrite installed, all 404's
|
||||
# can be sent to index.php, and everything works as normal.
|
||||
# Submitted by: ElliotHaughin
|
||||
|
||||
ErrorDocument 404 /index.php
|
||||
|
||||
</IfModule>
|
||||
|
||||
#Header add Access-Control-Allow-Origin "*"
|
||||
#Header add Access-Control-Expose-Headers "Access-Control-Allow-Origin"
|
||||
#Header add Access-Control-Allow-Headers "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With"
|
||||
#Header add Access-Control-Allow-Methods "POST, GET, PUT, DELETE, OPTIONS"
|
||||
#Header add Content-type "application/json"
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
class AddressToArea
|
||||
{
|
||||
|
||||
public static function get($db, $address_id, $city, $country)
|
||||
{
|
||||
$message = null;
|
||||
$address_id = (int) $address_id;
|
||||
$city_id = (int) $city;
|
||||
$country_code = pg_escape_string($country);
|
||||
|
||||
$result_areas = [];
|
||||
$postal_areas = [];
|
||||
$radius_areas = [];
|
||||
$plygon_areas = [];
|
||||
|
||||
// Step 1: Load address
|
||||
$q = "SELECT * FROM address WHERE id=${address_id}";
|
||||
$r = pg_query($db, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$address = pg_fetch_assoc($r);
|
||||
} else {
|
||||
return [null, "Address was not found"];
|
||||
}
|
||||
|
||||
// Step 2: Load areas for the city and country
|
||||
$q = "SELECT *
|
||||
FROM geofence_area
|
||||
WHERE "
|
||||
. (!empty($city_id) ? "city_id = ${city_id} AND" : '') .
|
||||
" country='${country_code}'";
|
||||
|
||||
$r = pg_query($db, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f = pg_fetch_assoc($r)) {
|
||||
if ($f["type"] == "postal") {
|
||||
$postal_areas[] = $f;
|
||||
}
|
||||
if ($f["type"] == "radius") {
|
||||
$radius_areas[] = $f;
|
||||
}
|
||||
if ($f["type"] == "polygon") {
|
||||
$plygon_areas[] = $f;
|
||||
}
|
||||
$raw_areas[] = $f;
|
||||
}
|
||||
} else {
|
||||
return [null, pg_last_error()];
|
||||
}
|
||||
if (count($postal_areas) < 1 && count($radius_areas) < 1 && count($plygon_areas) < 1) {
|
||||
return [null, "No areas defined for the city/country"];
|
||||
}
|
||||
|
||||
$result_areas = AddressToArea::getAreasForAddress($db, $address, $postal_areas, $radius_areas, $plygon_areas);
|
||||
|
||||
return [$result_areas, $message];
|
||||
}
|
||||
|
||||
public static function getAreasForAddress($db, $address, $postal_areas, $radius_areas, $plygon_areas)
|
||||
{
|
||||
$result_areas = [];
|
||||
|
||||
// Process postal codes
|
||||
if (count($postal_areas) > 0) {
|
||||
foreach ($postal_areas as $area) {
|
||||
$boundaries = json_decode($area["boundaries"], true);
|
||||
$codes = $boundaries["postal_code"];
|
||||
// if postal is not empty
|
||||
if (!empty($address["postal"])) {
|
||||
foreach ($codes as $code) {
|
||||
if ($code != "" && $code == substr($address["postal"], 0, strlen($code))) {
|
||||
$result_areas[] = $area;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if postal is empty
|
||||
} else if ($address["latitude"] != 0 && $address["longitude"] != 0) {
|
||||
$radius = 10; // 10Km
|
||||
$postals = self::getPostalFromLatLng($db, $address["latitude"], $address["longitude"], $radius);
|
||||
|
||||
$flag = false;
|
||||
foreach ($postals as $postal) {
|
||||
if ($flag) {
|
||||
break;
|
||||
}
|
||||
foreach ($codes as $code) {
|
||||
if ($code != "" && $code == substr($postal, 0, strlen($code))) {
|
||||
$result_areas[] = $area;
|
||||
$flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process radius
|
||||
if ($address["latitude"] != 0 && $address["longitude"] != 0 && count($radius_areas) > 0) {
|
||||
foreach ($radius_areas as $area) {
|
||||
$boundaries = json_decode($area["boundaries"], true);
|
||||
if (isset($boundaries['radius'])) {
|
||||
$radius = $boundaries['radius'];
|
||||
|
||||
// query to check if belongs to a radius area
|
||||
$query = "SELECT ST_DWithin('" . $area['location'] . "', ST_SetSRID(ST_Point (" . $address["longitude"] . ", " . $address["latitude"] . "), 4326)::geography, ${radius}) as iscorrect";
|
||||
$data = pg_fetch_all(pg_query($db, $query));
|
||||
|
||||
if ($data[0]['iscorrect'] == "t") {
|
||||
$result_areas[] = $area;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process polygon
|
||||
if ($address["latitude"] != 0 && $address["longitude"] != 0 && count($plygon_areas) > 0) {
|
||||
foreach ($plygon_areas as $area) {
|
||||
$boundaries = json_decode($area["boundaries"], true);
|
||||
if (isset($boundaries['polygon'])) {
|
||||
$polygon = $boundaries['polygon'];
|
||||
$polygonCoords = [];
|
||||
foreach ($polygon as $coord) {
|
||||
$polygonCoords[] = "$coord[0] $coord[1]";
|
||||
}
|
||||
$polygonCoordsString = implode(",", $polygonCoords);
|
||||
|
||||
// query to check if belongs to a polygon area
|
||||
$query = "SELECT ST_Contains(ST_GeomFromText('POLYGON((${polygonCoordsString}))', 4326), ST_SetSRID(ST_Point (" . $address["longitude"] . ", " . $address["latitude"] . "), 4326)) as iscorrect";
|
||||
$data = pg_fetch_all(pg_query($db, $query));
|
||||
|
||||
if ($data[0]['iscorrect'] == "t") {
|
||||
$result_areas[] = $area;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result_areas;
|
||||
}
|
||||
|
||||
/**
|
||||
* get postal array from latitude, longitude
|
||||
*/
|
||||
public static function getPostalFromLatLng($db, float $latitude, float $longitude, int $distance_in_km): array
|
||||
{
|
||||
$earth_radius = 6371;
|
||||
$km_per_degree_lat = 111.2;
|
||||
$pi = 3.14 / 180;
|
||||
|
||||
$query = " SELECT postal FROM (
|
||||
SELECT
|
||||
CASE
|
||||
WHEN
|
||||
$latitude = address.latitude AND $longitude = address.longitude THEN 0
|
||||
ELSE
|
||||
$earth_radius * acos(
|
||||
cos( radians( {$latitude}) )
|
||||
* cos( radians( address.latitude ) )
|
||||
* cos( radians( address.longitude ) - radians( {$longitude} ) )
|
||||
+ sin( radians( {$latitude}) )
|
||||
* sin( radians( address.latitude ) ) )
|
||||
END AS distance
|
||||
, *
|
||||
FROM address
|
||||
WHERE
|
||||
address.postal IS NOT NULL
|
||||
AND address.latitude BETWEEN " . ($latitude - ($distance_in_km / $km_per_degree_lat)) .
|
||||
" AND " . ($latitude + ($distance_in_km / $km_per_degree_lat));
|
||||
|
||||
$delta = round($distance_in_km / ($km_per_degree_lat * COS(deg2rad($longitude))), 10);
|
||||
|
||||
// Bounding box for speed - latitude within range (longtitude to km not linear)
|
||||
if (cos($longitude * $pi) > 0) {
|
||||
|
||||
$from = $longitude - $delta;
|
||||
$to = $longitude + $delta;
|
||||
|
||||
$query .=
|
||||
" AND address.longitude" .
|
||||
" BETWEEN " . $from .
|
||||
" AND " . $to;
|
||||
|
||||
} else {
|
||||
|
||||
$from = $longitude + $delta;
|
||||
$to = $longitude - $delta;
|
||||
|
||||
$query .=
|
||||
" AND address.longitude" .
|
||||
" BETWEEN " . $from .
|
||||
" AND " . $to;
|
||||
|
||||
}
|
||||
|
||||
// distance limit for circle
|
||||
$query .= " ) address
|
||||
WHERE distance < " . $distance_in_km;
|
||||
|
||||
$rs = pg_query($db, $query);
|
||||
|
||||
if (!$rs) {
|
||||
throw new Exception(pg_last_error($db));
|
||||
}
|
||||
|
||||
return pg_fetch_all($rs) ? array_column(pg_fetch_all($rs), 'postal') : [];
|
||||
}
|
||||
}
|
||||
// vi:ts=2
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
class AddressToAreaApi extends Api {
|
||||
public $apiName = 'addresstoarea';
|
||||
|
||||
public function __construct($requestUri, $encryption=true) {
|
||||
$encryption = false; // We do not need encryption for this class
|
||||
parent::__construct($requestUri, $encryption);
|
||||
//$this->encryption = $encryption;
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/SAVVY/geofencearea/api/addresstoarea?address_id={address_id}",
|
||||
* security={{"token": {}}},
|
||||
* summary="Geocode address id to a geofence area",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="area list address belongs to",
|
||||
* @OA\JsonContent(
|
||||
* type="object"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function indexAction() {
|
||||
$message = 'No areas found';
|
||||
|
||||
$address_id = $this->requestParams['address_id'] ?? 0;
|
||||
$city = $this->requestParams['city'] ?? 0;
|
||||
$country = $this->requestParams['country'] ?? '';
|
||||
|
||||
try {
|
||||
if ($address_id<1) {
|
||||
throw new Exception("Invalid address ID");
|
||||
}
|
||||
|
||||
if (!in_array(strtoupper($country), ['SG','US']) ) { // Singapore and USA only for now
|
||||
throw new Exception("Invalid country");
|
||||
}
|
||||
|
||||
$db = new Db();
|
||||
list($res, $err) = AddressToArea::get( $db->getConnect(), $address_id, $city, $country );
|
||||
return $this->response(
|
||||
[
|
||||
"areas" => $res,
|
||||
"error" => $err
|
||||
], 200 );
|
||||
|
||||
} catch (Exception $e) {
|
||||
$message = $e->getMessage();
|
||||
}
|
||||
return $this->response(
|
||||
[
|
||||
"areas" => NULL,
|
||||
"error" => $message
|
||||
], 404);
|
||||
}
|
||||
|
||||
public function viewAction() {
|
||||
|
||||
}
|
||||
|
||||
public function createAction() {
|
||||
|
||||
}
|
||||
|
||||
public function updateAction() {
|
||||
|
||||
}
|
||||
|
||||
public function deleteAction() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
<?php
|
||||
|
||||
class GeofenceAreaApi extends Api
|
||||
{
|
||||
public $apiName = 'geofencearea';
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/v1/geofencearea/api/geofencearea/countryApi",
|
||||
* summary="Get list of countries",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="return all geofence area countries",
|
||||
* @OA\JsonContent(
|
||||
* type="object"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function countryApi()
|
||||
{
|
||||
$db = new Db();
|
||||
$result = GeofenceAreaModel::getCountryListWithoutPagination($db->getConnect());
|
||||
|
||||
return $this->response($result, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/v1/geofencearea/api/geofencearea/cityApi?country_code={country_code}",
|
||||
* summary="Get list of cities",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="city data",
|
||||
* @OA\JsonContent(
|
||||
* type="object"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function cityApi()
|
||||
{
|
||||
$db = new Db();
|
||||
|
||||
$searchParams = $this->requestParams;
|
||||
$result = GeofenceAreaModel::getCityListWithoutPagination($db->getConnect(), $searchParams);
|
||||
|
||||
return $this->response($result, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/v1/geofencearea/api/geofencearea/boundariesApi?city_id={city_id}&country_code={country_code}",
|
||||
* summary="Get list of GPS areas by city and country_code",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="area data",
|
||||
* @OA\JsonContent(
|
||||
* type="object"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function boundariesApi()
|
||||
{
|
||||
$db = new Db();
|
||||
|
||||
$searchParams = $this->requestParams;
|
||||
$result = GeofenceAreaModel::getAreaListWithoutPagination($db->getConnect(), $searchParams);
|
||||
|
||||
return $this->response($result, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/v1/geofencearea/api/geofencearea/tripsApi?from_area_id={from_area_id}&to_area_id={to_area_id}&transport_provider_id={transport_provider_id}",
|
||||
* summary="Get list of trips between areas (filter by transport_provider_id)",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="trip data",
|
||||
* @OA\JsonContent(
|
||||
* type="object"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function tripsApi()
|
||||
{
|
||||
$db = new Db();
|
||||
$searchParams = $this->requestParams;
|
||||
$startAreaId = $searchParams['from_area_id'] ?? null;
|
||||
$endAreaId = $searchParams['to_area_id'] ?? null;
|
||||
|
||||
if (!$startAreaId || !$endAreaId) {
|
||||
$result = [
|
||||
'success' => false,
|
||||
'message' => 'missing parameter values (from_area_id and to_area_id parameter are required).'
|
||||
];
|
||||
return $this->response($result, 200);
|
||||
}
|
||||
|
||||
$result = GeofenceAreaModel::getTripListBetweenArea($db->getConnect(), $startAreaId, $endAreaId, $searchParams);
|
||||
return $this->response($result, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/v1/geofencearea/api/geofencearea/priceComparisonApi?from_area_id={from_area_id}&to_area_id={to_area_id}",
|
||||
* summary="Compare price between areas (group by transport_provider_id)",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="data",
|
||||
* @OA\JsonContent(
|
||||
* type="object"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function priceComparisonApi()
|
||||
{
|
||||
$db = new Db();
|
||||
$searchParams = $this->requestParams;
|
||||
$startAreaId = $searchParams['from_area_id'] ?? null;
|
||||
$endAreaId = $searchParams['to_area_id'] ?? null;
|
||||
|
||||
if (!$startAreaId || !$endAreaId) {
|
||||
$result = [
|
||||
'success' => false,
|
||||
'message' => 'missing parameter values (from_area_id and to_area_id parameter are required).'
|
||||
];
|
||||
return $this->response($result, 200);
|
||||
}
|
||||
|
||||
$data = GeofenceAreaModel::priceComparison($db->getConnect(), $startAreaId, $endAreaId);
|
||||
|
||||
$result = [
|
||||
'success' => true,
|
||||
'data' => $data ?: []
|
||||
];
|
||||
return $this->response($result, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/v1/geofencearea/api/geofencearea/priceComparisonFromAreasToOneDestinationApi?from_area_id_list=3,4,5,2,7&to_area_id=9",
|
||||
* summary="Compare price from list of areas to one destination (group by transport_provider_id)",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="data",
|
||||
* @OA\JsonContent(
|
||||
* type="object"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function priceComparisonFromAreasToOneDestinationApi()
|
||||
{
|
||||
$db = new Db();
|
||||
$searchParams = $this->requestParams;
|
||||
|
||||
// with params format fo ....&from_area_id_list=2,3,4,5,8,9&to_area_id=15
|
||||
$startAreaIdList = $searchParams['from_area_id_list'] ?? null;
|
||||
$endAreaId = $searchParams['to_area_id'] ?? null;
|
||||
|
||||
if (!$startAreaIdList || !$endAreaId) {
|
||||
$result = [
|
||||
'success' => false,
|
||||
'message' => 'missing parameter values (from_area_id_list and to_area_id parameter are required).'
|
||||
];
|
||||
return $this->response($result, 200);
|
||||
}
|
||||
|
||||
// convert from_area_id_list=2,3,4,5,8,9 => [2,3,4,5,8,9]
|
||||
$startAreaIdList = explode(',', $startAreaIdList);
|
||||
|
||||
$data = [];
|
||||
foreach ($startAreaIdList as $startAreaId) {
|
||||
$data[] = GeofenceAreaModel::priceComparison($db->getConnect(), $startAreaId, $endAreaId);
|
||||
}
|
||||
|
||||
$result = [
|
||||
'success' => true,
|
||||
'data' => $data ?: []
|
||||
];
|
||||
return $this->response($result, 200);
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function viewAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function createAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function updateAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function deleteAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected function getAction()
|
||||
{
|
||||
$method = $this->method;
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$pos = strpos($this->requestUri[0], '?');
|
||||
if ($pos !== false && $pos == 0) {
|
||||
// We want to get "all"
|
||||
$this->requestUri[0] = "all" . $this->requestUri[0];
|
||||
}
|
||||
$tok = strtok($this->requestUri[0], '?');
|
||||
|
||||
if ($tok === false || $tok == 'all') {
|
||||
return 'indexAction';
|
||||
} else {
|
||||
return $tok;
|
||||
}
|
||||
break;
|
||||
case 'POST':
|
||||
return 'createAction';
|
||||
break;
|
||||
case 'PUT':
|
||||
return 'updateAction';
|
||||
break;
|
||||
case 'DELETE':
|
||||
return 'deleteAction';
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,619 @@
|
||||
<?php
|
||||
|
||||
class GeofenceAreaModel
|
||||
{
|
||||
public static function getCountryListWithPagination($db, $page = 1, $perPage = 10)
|
||||
{
|
||||
$offset = ($page - 1) * $perPage;
|
||||
if ($offset < 0) {
|
||||
$offset = 0;
|
||||
}
|
||||
|
||||
$query_total = "SELECT count(*) FROM geofence_area_country";
|
||||
|
||||
$query = "SELECT
|
||||
id, country as country_code, latitude, longitude, location, radius
|
||||
FROM
|
||||
geofence_area_country
|
||||
ORDER BY
|
||||
id desc limit '" . pg_escape_string($perPage) . "' offset '" . pg_escape_string($offset) . "'";
|
||||
|
||||
$rs = pg_query($db, $query);
|
||||
$rs_total = pg_query($db, $query_total);
|
||||
|
||||
$data = pg_fetch_all($rs);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'data' => !empty($data) ? $data : [],
|
||||
'total' => pg_fetch_result($rs_total, 'count'),
|
||||
'page' => $page,
|
||||
];
|
||||
}
|
||||
|
||||
public static function getCountryListWithoutPagination($db)
|
||||
{
|
||||
$query = "SELECT
|
||||
id, country as country_code, latitude, longitude, location, radius
|
||||
FROM
|
||||
geofence_area_country
|
||||
ORDER BY
|
||||
id desc";
|
||||
|
||||
$rs = pg_query($db, $query);
|
||||
$data = pg_fetch_all($rs);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'data' => !empty($data) ? $data : []
|
||||
];
|
||||
}
|
||||
|
||||
public static function getCityListWithPagination($db, $page = 1, $perPage = 10)
|
||||
{
|
||||
$offset = ($page - 1) * $perPage;
|
||||
if ($offset < 0) {
|
||||
$offset = 0;
|
||||
}
|
||||
|
||||
$query_total = "SELECT count(*) FROM geofence_area_city";
|
||||
|
||||
$query = "SELECT
|
||||
id, city, country as country_code, latitude, longitude, location, radius
|
||||
FROM
|
||||
geofence_area_city
|
||||
ORDER BY
|
||||
id desc limit '" . pg_escape_string($perPage) . "' offset '" . pg_escape_string($offset) . "'";
|
||||
|
||||
$rs = pg_query($db, $query);
|
||||
$rs_total = pg_query($db, $query_total);
|
||||
|
||||
$data = pg_fetch_all($rs);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'data' => !empty($data) ? $data : [],
|
||||
'total' => pg_fetch_result($rs_total, 'count'),
|
||||
'page' => $page,
|
||||
];
|
||||
}
|
||||
|
||||
public static function getCityListWithoutPagination($db, $search = [])
|
||||
{
|
||||
$_self = new self;
|
||||
|
||||
$query = "SELECT
|
||||
id, city, country as country_code,
|
||||
latitude, longitude, location,
|
||||
radius
|
||||
FROM
|
||||
geofence_area_city";
|
||||
|
||||
$whereQuery = '';
|
||||
$order = " ORDER BY id desc";
|
||||
|
||||
if (!empty($search["country_code"])) {
|
||||
$condition = " LOWER(country) = '" . pg_escape_string(strtolower($search["country_code"])) . "'";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
|
||||
$query .= $whereQuery;
|
||||
|
||||
}
|
||||
if (!empty($search["latitude"]) &&
|
||||
!empty($search["longitude"]) &&
|
||||
!empty($search["radius"])) {
|
||||
|
||||
$earth_radius = 6371;
|
||||
$km_per_degree_lat = 111.2;
|
||||
$pi = 3.14/180;
|
||||
$latitude = $search["latitude"];
|
||||
$longitude = $search["longitude"];
|
||||
$distance_in_km = $search["radius"];
|
||||
|
||||
$query = " SELECT id
|
||||
, city
|
||||
, country as country_code
|
||||
, latitude
|
||||
, longitude
|
||||
, location
|
||||
, radius
|
||||
FROM (
|
||||
SELECT (
|
||||
$earth_radius * acos(
|
||||
cos( radians( {$latitude}) )
|
||||
* cos( radians( latitude ) )
|
||||
* cos( radians( longitude ) - radians( {$longitude} ) )
|
||||
+ sin( radians( {$latitude}) )
|
||||
* sin( radians( latitude ) ))
|
||||
) AS distance
|
||||
, id
|
||||
, city
|
||||
, country
|
||||
, latitude
|
||||
, longitude
|
||||
, location
|
||||
, radius
|
||||
FROM geofence_area_city
|
||||
WHERE
|
||||
latitude BETWEEN " . ($latitude - ($distance_in_km / $km_per_degree_lat)) .
|
||||
" AND " . ($latitude + ($distance_in_km / $km_per_degree_lat));
|
||||
|
||||
$delta = round($distance_in_km / ($km_per_degree_lat * COS(deg2rad($longitude))), 10);
|
||||
|
||||
// Bounding box for speed - latitude within range (longtitude to km not linear)
|
||||
if(cos($longitude * $pi) > 0) {
|
||||
|
||||
$from = $longitude - $delta;
|
||||
$to = $longitude + $delta;
|
||||
|
||||
$query .=
|
||||
" AND longitude" .
|
||||
" BETWEEN " . $from .
|
||||
" AND " . $to;
|
||||
|
||||
} else {
|
||||
|
||||
$from = $longitude + $delta;
|
||||
$to = $longitude - $delta;
|
||||
|
||||
$query .=
|
||||
" AND longitude" .
|
||||
" BETWEEN " . $from .
|
||||
" AND " . $to;
|
||||
|
||||
}
|
||||
|
||||
// distance limit for circle
|
||||
$query .= " ) geofence_area_city
|
||||
WHERE distance < " . $distance_in_km;
|
||||
}
|
||||
|
||||
$query .= $order;
|
||||
|
||||
$rs = pg_query($db, $query);
|
||||
$data = pg_fetch_all($rs);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'data' => !empty($data) ? $data : []
|
||||
];
|
||||
}
|
||||
|
||||
public static function getAreaListWithPagination($db, $page = 1, $perPage = 10, $search = [])
|
||||
{
|
||||
$_self = new self;
|
||||
|
||||
$offset = ($page - 1) * $perPage;
|
||||
if ($offset < 0) {
|
||||
$offset = 0;
|
||||
}
|
||||
|
||||
$whereQuery = '';
|
||||
if (isset($search["city_id"])) {
|
||||
$condition = " geofence_area_city.id = '" . pg_escape_string($search["city_id"]) . "'";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
}
|
||||
|
||||
$query_total = "SELECT count(*)
|
||||
FROM
|
||||
geofence_area
|
||||
JOIN geofence_area_city ON geofence_area_city.id = geofence_area.city_id " . $whereQuery;
|
||||
|
||||
$query = "SELECT
|
||||
geofence_area.id, geofence_area.name, geofence_area_city.city, geofence_area.country as country_code, geofence_area.latitude, geofence_area.longitude,
|
||||
geofence_area.location, geofence_area.type, geofence_area.boundaries
|
||||
FROM
|
||||
geofence_area
|
||||
JOIN geofence_area_city ON geofence_area_city.id = geofence_area.city_id
|
||||
" . $whereQuery . "
|
||||
ORDER BY
|
||||
id desc limit '" . pg_escape_string($perPage) . "' offset '" . pg_escape_string($offset) . "'";
|
||||
|
||||
$rs = pg_query($db, $query);
|
||||
$rs_total = pg_query($db, $query_total);
|
||||
|
||||
$data = pg_fetch_all($rs);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'data' => !empty($data) ? $data : [],
|
||||
'total' => pg_fetch_result($rs_total, 'count'),
|
||||
'page' => $page,
|
||||
];
|
||||
}
|
||||
|
||||
public static function getAreaListWithoutPagination($db, $search = [])
|
||||
{
|
||||
$_self = new self;
|
||||
$whereQuery = '';
|
||||
|
||||
if (!empty($search["city_id"])) {
|
||||
$condition = " geofence_area_city.id = '" . pg_escape_string($search["city_id"]) . "'";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
}
|
||||
|
||||
if (!empty($search["country_code"])) {
|
||||
$condition = " LOWER(geofence_area.country) = '" . pg_escape_string(strtolower($search["country_code"])) . "'";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
}
|
||||
|
||||
$query = "SELECT
|
||||
geofence_area.id, geofence_area.name, geofence_area_city.city, geofence_area.country as country_code, geofence_area.latitude, geofence_area.longitude,
|
||||
geofence_area.location, geofence_area.type, geofence_area.boundaries
|
||||
FROM
|
||||
geofence_area
|
||||
JOIN geofence_area_city ON geofence_area_city.id = geofence_area.city_id
|
||||
" . $whereQuery . "
|
||||
ORDER BY
|
||||
id desc";
|
||||
|
||||
$rs = pg_query($db, $query);
|
||||
$data = pg_fetch_all($rs);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'data' => !empty($data) ? $data : []
|
||||
];
|
||||
}
|
||||
|
||||
public static function getTripListBetweenArea($db, $startAreaId, $endAreaId, $search = [])
|
||||
{
|
||||
$_self = new self;
|
||||
$whereQuery = '';
|
||||
if (!empty($search["transport_provider_id"])) {
|
||||
$condition = " parsedemail_item.transport_provider_id = '" . pg_escape_string($search["transport_provider_id"]) . "'";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
}
|
||||
|
||||
// 1) Define geofenced areas, get list of areas
|
||||
$startArea = $_self->getArea($db, $startAreaId);
|
||||
$endArea = $_self->getArea($db, $endAreaId);
|
||||
|
||||
if (!$startArea || !$endArea) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Can not find area.'
|
||||
];
|
||||
}
|
||||
|
||||
// 2. Select trips where "from" falls into origin area and "to" falls into destination area
|
||||
$startBoundaries = json_decode($startArea['boundaries'], true);
|
||||
$endBoundaries = json_decode($endArea['boundaries'], true);
|
||||
if ($startArea['type'] === 'radius') {
|
||||
if (isset($startBoundaries['radius'])) {
|
||||
$radius = $startBoundaries['radius'];
|
||||
$condition = " ST_DWithin('" . $startArea['location'] . "', startAddr.geometry, " . $radius . ") ";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing radius in boundaries field.'
|
||||
];
|
||||
}
|
||||
} else if ($startArea['type'] === 'postal') {
|
||||
if (is_array($startBoundaries) && array_key_exists("postal_code",$startBoundaries) && is_array($startBoundaries["postal_code"]) && count($startBoundaries["postal_code"]) > 0) {
|
||||
$condition = "";
|
||||
foreach ($startBoundaries['postal_code'] as $code) {
|
||||
if ($condition != "") {
|
||||
$condition .= " OR ";
|
||||
}
|
||||
$condition .= " LEFT(startAddr.postal, " . strlen($code) . ") = '${code}' ";
|
||||
}
|
||||
|
||||
$condition = "(${condition})";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing postal_code in boundaries field.'
|
||||
];
|
||||
}
|
||||
} else if ($startArea['type'] === 'polygon') {
|
||||
if (isset($startBoundaries['polygon'])) {
|
||||
$polygon = $startBoundaries['polygon'];
|
||||
|
||||
$polygonCoords = [];
|
||||
foreach ($polygon as $coord) {
|
||||
$polygonCoords[] = "$coord[0] $coord[1]";
|
||||
}
|
||||
$polygonCoordsString = implode(",", $polygonCoords);
|
||||
|
||||
$condition = " ST_Contains(ST_GeomFromText('POLYGON((${polygonCoordsString}))', 4326), startAddr.geometry::geometry) ";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing polygon in boundaries field.'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($endArea['type'] === 'radius') {
|
||||
if (isset($endBoundaries['radius'])) {
|
||||
$radius = $endBoundaries['radius'];
|
||||
$condition = " ST_DWithin('" . $endArea['location'] . "', endAddr.geometry, " . $radius . ") ";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing radius in boundaries field.'
|
||||
];
|
||||
}
|
||||
} else if ($endArea['type'] === 'postal') {
|
||||
if (is_array($endBoundaries) && array_key_exists("postal_code",$endBoundaries) && is_array($endBoundaries["postal_code"]) && count($endBoundaries["postal_code"]) > 0) {
|
||||
$condition = "";
|
||||
foreach ($endBoundaries['postal_code'] as $code) {
|
||||
if ($condition != "") {
|
||||
$condition .= " OR ";
|
||||
}
|
||||
$condition .= " LEFT(endAddr.postal, " . strlen($code) . ") = '${code}' ";
|
||||
}
|
||||
|
||||
$condition = "(${condition})";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing postal_code in boundaries field.'
|
||||
];
|
||||
}
|
||||
} else if ($endArea['type'] === 'polygon') {
|
||||
if (isset($endBoundaries['polygon'])) {
|
||||
$polygon = $endBoundaries['polygon'];
|
||||
|
||||
$polygonCoords = [];
|
||||
foreach ($polygon as $coord) {
|
||||
$polygonCoords[] = "$coord[0] $coord[1]";
|
||||
}
|
||||
$polygonCoordsString = implode(",", $polygonCoords);
|
||||
|
||||
$condition = " ST_Contains(ST_GeomFromText('POLYGON((${polygonCoordsString}))', 4326), endAddr.geometry::geometry) ";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing polygon in boundaries field.'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// only get trips within last year
|
||||
$numberOfDays = 365;
|
||||
$condition = " parsedemail_item.travel_date BETWEEN NOW() - INTERVAL '" . $numberOfDays . " days' AND NOW() ";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
|
||||
$tripQuery =
|
||||
"SELECT
|
||||
parsedemail_item.id as trip_id, parsedemail_item.transport_provider_id, startAddr.address as start_address, endAddr.address as end_address
|
||||
FROM
|
||||
parsedemail_item
|
||||
JOIN address AS startAddr ON (startAddr.id = parsedemail_item.location_start_id AND transport_provider_id IS NOT NULL
|
||||
AND LOWER(startAddr.country) = '" . strtolower($startArea['country_code']) . "')
|
||||
JOIN address AS endAddr ON (endAddr.id = parsedemail_item.location_end_id
|
||||
AND LOWER(endAddr.country) = '" . strtolower($endArea['country_code']) . "')
|
||||
" . $whereQuery;
|
||||
|
||||
$data = pg_fetch_all(pg_query($db, $tripQuery));
|
||||
|
||||
$result = [
|
||||
'from_area' => $startArea,
|
||||
'to_area' => $endArea,
|
||||
'trip_list' => $data ?: []
|
||||
];
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'data' => $result ?: []
|
||||
];
|
||||
}
|
||||
|
||||
public static function priceComparison($db, $startAreaId, $endAreaId)
|
||||
{
|
||||
$_self = new self;
|
||||
|
||||
// 1) Define geofenced areas, get list of areas
|
||||
$startArea = $_self->getArea($db, $startAreaId);
|
||||
$endArea = $_self->getArea($db, $endAreaId);
|
||||
|
||||
if (!$startArea || !$endArea) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Can not find area.'
|
||||
];
|
||||
}
|
||||
|
||||
$tripQuery = "SELECT ROUND(SUM(average_total)/SUM(average_count), 2) as avg_price, transport_provider_id";
|
||||
$tripQuery.= " FROM geofence_area_average_quotes ";
|
||||
$tripQuery.= " WHERE area_start_id=${startAreaId} AND area_end_id=${endAreaId}";
|
||||
$tripQuery.= " GROUP BY transport_provider_id";
|
||||
|
||||
$data = pg_fetch_all(pg_query($db, $tripQuery));
|
||||
error_log($tripQuery);
|
||||
|
||||
$result = [
|
||||
'from_area' => $startArea,
|
||||
'to_area' => $endArea,
|
||||
'price_comparison' => $data ?: []
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function priceComparisonOld($db, $startAreaId, $endAreaId)
|
||||
{
|
||||
$_self = new self;
|
||||
|
||||
// 1) Define geofenced areas, get list of areas
|
||||
$startArea = $_self->getArea($db, $startAreaId);
|
||||
$endArea = $_self->getArea($db, $endAreaId);
|
||||
|
||||
if (!$startArea || !$endArea) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Can not find area.'
|
||||
];
|
||||
}
|
||||
|
||||
// 2. Select trips where "from" falls into origin area and "to" falls into destination area
|
||||
$whereQuery = '';
|
||||
$startBoundaries = json_decode($startArea['boundaries'], true);
|
||||
$endBoundaries = json_decode($endArea['boundaries'], true);
|
||||
if ($startArea['type'] === 'radius') {
|
||||
if (isset($startBoundaries['radius'])) {
|
||||
$radius = $startBoundaries['radius'];
|
||||
$condition = " ST_DWithin('" . $startArea['location'] . "', startAddr.geometry, " . $radius . ") ";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing radius in boundaries field.'
|
||||
];
|
||||
}
|
||||
} else if ($startArea['type'] === 'postal') {
|
||||
if (is_array($startBoundaries) && array_key_exists("postal_code",$startBoundaries) && is_array($startBoundaries["postal_code"]) && count($startBoundaries["postal_code"]) > 0) {
|
||||
$condition = "";
|
||||
foreach ($startBoundaries['postal_code'] as $code) {
|
||||
if ($condition != "") {
|
||||
$condition .= " OR ";
|
||||
}
|
||||
$condition .= " LEFT(startAddr.postal, " . strlen($code) . ") = '${code}' ";
|
||||
}
|
||||
|
||||
$condition = "(${condition})";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing postal_code in boundaries field.'
|
||||
];
|
||||
}
|
||||
} else if ($startArea['type'] === 'polygon') {
|
||||
if (isset($startBoundaries['polygon'])) {
|
||||
$polygon = $startBoundaries['polygon'];
|
||||
|
||||
$polygonCoords = [];
|
||||
foreach ($polygon as $coord) {
|
||||
$polygonCoords[] = "$coord[0] $coord[1]";
|
||||
}
|
||||
$polygonCoordsString = implode(",", $polygonCoords);
|
||||
|
||||
$condition = " ST_Contains(ST_GeomFromText('POLYGON((${polygonCoordsString}))', 4326), startAddr.geometry::geometry) ";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing polygon in boundaries field.'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($endArea['type'] === 'radius') {
|
||||
if (isset($endBoundaries['radius'])) {
|
||||
$radius = $endBoundaries['radius'];
|
||||
$condition = " ST_DWithin('" . $endArea['location'] . "', endAddr.geometry, " . $radius . ") ";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing radius in boundaries field.'
|
||||
];
|
||||
}
|
||||
} else if ($endArea['type'] === 'postal') {
|
||||
if (is_array($endBoundaries) && array_key_exists("postal_code",$endBoundaries) && is_array($endBoundaries["postal_code"]) && count($endBoundaries["postal_code"]) > 0) {
|
||||
$condition = "";
|
||||
foreach ($endBoundaries['postal_code'] as $code) {
|
||||
if ($condition != "") {
|
||||
$condition .= " OR ";
|
||||
}
|
||||
$condition .= " LEFT(endAddr.postal, " . strlen($code) . ") = '${code}' ";
|
||||
}
|
||||
|
||||
$condition = "(${condition})";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing postal_code in boundaries field.'
|
||||
];
|
||||
}
|
||||
} else if ($endArea['type'] === 'polygon') {
|
||||
if (isset($endBoundaries['polygon'])) {
|
||||
$polygon = $endBoundaries['polygon'];
|
||||
|
||||
$polygonCoords = [];
|
||||
foreach ($polygon as $coord) {
|
||||
$polygonCoords[] = "$coord[0] $coord[1]";
|
||||
}
|
||||
$polygonCoordsString = implode(",", $polygonCoords);
|
||||
|
||||
$condition = " ST_Contains(ST_GeomFromText('POLYGON((${polygonCoordsString}))', 4326), endAddr.geometry::geometry) ";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing polygon in boundaries field.'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Filter pricing by transport_provider_id and calculate average within last year
|
||||
|
||||
// only get trips within last year
|
||||
$numberOfDays = 365;
|
||||
$condition = " parsedemail_item.travel_date BETWEEN NOW() - INTERVAL '" . $numberOfDays . " days' AND NOW() ";
|
||||
$whereQuery = $_self->checkCondition($condition, $whereQuery);
|
||||
|
||||
$tripQuery =
|
||||
"SELECT
|
||||
ROUND(AVG(parsedemail_item.cost), 2) as avg_price, parsedemail_item.transport_provider_id
|
||||
FROM
|
||||
parsedemail_item
|
||||
JOIN address AS startAddr ON (startAddr.id = parsedemail_item.location_start_id AND transport_provider_id IS NOT NULL
|
||||
AND LOWER(startAddr.country) = '" . strtolower($startArea['country_code']) . "')
|
||||
JOIN address AS endAddr ON (endAddr.id = parsedemail_item.location_end_id
|
||||
AND LOWER(endAddr.country) = '" . strtolower($endArea['country_code']) . "')
|
||||
" . $whereQuery . "
|
||||
GROUP BY parsedemail_item.transport_provider_id
|
||||
";
|
||||
|
||||
|
||||
|
||||
$data = pg_fetch_all(pg_query($db, $tripQuery));
|
||||
|
||||
$result = [
|
||||
'from_area' => $startArea,
|
||||
'to_area' => $endArea,
|
||||
'price_comparison' => $data ?: []
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function checkCondition($condition, $query)
|
||||
{
|
||||
if (strpos($query, 'WHERE') === false) {
|
||||
$query .= " WHERE $condition";
|
||||
} else {
|
||||
$query .= " AND $condition";
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
public static function getArea($db, $id)
|
||||
{
|
||||
$query = "SELECT
|
||||
geofence_area.id, geofence_area.name, geofence_area.country as country_code, geofence_area.latitude, geofence_area.longitude,
|
||||
geofence_area.location, geofence_area.type, geofence_area.boundaries
|
||||
FROM
|
||||
geofence_area
|
||||
WHERE
|
||||
geofence_area.id = $id
|
||||
LIMIT 1
|
||||
";
|
||||
|
||||
$rs = pg_query($db, $query);
|
||||
$data = pg_fetch_assoc($rs);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
class HourlyAverages {
|
||||
|
||||
public static function get($db, $from_address, $to_address, $city, $country) {
|
||||
$message = NULL;
|
||||
$city_id = (int)$city;
|
||||
$country_code = pg_escape_string($country);
|
||||
|
||||
$from_areas = [];
|
||||
$to_areas = [];
|
||||
|
||||
$postal_areas = [];
|
||||
$radius_areas = [];
|
||||
$plygon_areas = [];
|
||||
|
||||
// Load areas for the city and country
|
||||
$q = "SELECT * FROM geofence_area WHERE city_id=${city_id} AND country='${country_code}'";
|
||||
$r = pg_query($db, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
if ($f["type"]=="postal") {
|
||||
$postal_areas[] = $f;
|
||||
}
|
||||
if ($f["type"]=="radius") {
|
||||
$radius_areas[] = $f;
|
||||
}
|
||||
if ($f["type"]=="polygon") {
|
||||
$plygon_areas[] = $f;
|
||||
}
|
||||
$raw_areas[] = $f;
|
||||
}
|
||||
} else {
|
||||
return [NULL,pg_last_error()];
|
||||
}
|
||||
if (count($postal_areas)<1 && count($radius_areas)<1 && count($plygon_areas)<1) {
|
||||
return [NULL,"No areas defined for the city"];
|
||||
}
|
||||
|
||||
$from_areas = AddressToArea::getAreasForAddress($db,$from_address,$postal_areas,$radius_areas,$plygon_areas);
|
||||
if (!is_array($from_areas) || count($from_areas)<1) {
|
||||
return [NULL,"Cannot geocode from address to an area"];
|
||||
}
|
||||
|
||||
$to_areas = AddressToArea::getAreasForAddress($db,$to_address,$postal_areas,$radius_areas,$plygon_areas);
|
||||
if (!is_array($to_areas) || count($to_areas)<1) {
|
||||
return [NULL,"Cannot geocode to address to an area"];
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
$q = "SELECT * FROM geofence_area_average_quotes ";
|
||||
$q.= " WHERE area_start_id=".$from_areas[0]["id"]." AND area_end_id=".$to_areas[0]["id"];
|
||||
$q.= " ORDER BY transport_provider_id, hour";
|
||||
$r = pg_query($db, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
if (!array_key_exists($f['transport_provider_id'],$data)) {
|
||||
$data[$f['transport_provider_id']] = [];
|
||||
}
|
||||
$data[$f['transport_provider_id']][$f['hour']] = $f;
|
||||
}
|
||||
}
|
||||
$certainty = HourlyAverages::calculateCertainty($data);
|
||||
|
||||
$result_areas = [
|
||||
'from_areas' => $from_areas,
|
||||
'to_areas' => $to_areas,
|
||||
'hourlyaverages' => $data,
|
||||
'certainty' => $certainty
|
||||
];
|
||||
|
||||
return [$result_areas, $message];
|
||||
}
|
||||
|
||||
|
||||
public static function calculateCertainty($data) {
|
||||
$vendors = []; // Vendors to process
|
||||
$hours = []; // Transposition matrix
|
||||
$Pi = []; // Certainity by vendor (current hour)
|
||||
$Wi = []; // Weight by vendor (current hour)
|
||||
$Si = []; // Sum by vendor per hout
|
||||
$Ri = []; // Certainty per hour
|
||||
foreach ($data as $key=>$val) {
|
||||
$vendors[] = $key;
|
||||
$Pi[$key] = 0;
|
||||
$Wi[$key] = 0;
|
||||
}
|
||||
for ($i=0; $i<24; $i++) {
|
||||
$hours[$i] = [];
|
||||
$Si[$i] = 0;
|
||||
$Ri[$i] = 0;
|
||||
foreach ($vendors as $vendor) {
|
||||
$hours[$i][$vendor] = NULL;
|
||||
}
|
||||
}
|
||||
foreach ($data as $key=>$val) {
|
||||
foreach ($val as $hour=>$f) {
|
||||
$hours[$f['hour']][$f['transport_provider_id']] = [
|
||||
'average_cost' => $f['average_cost'],
|
||||
'average_total' => $f['average_total'],
|
||||
'average_count' => $f['average_count']
|
||||
];
|
||||
$Si[$f['hour']] += $f['average_count'];
|
||||
}
|
||||
}
|
||||
for ($i=0; $i<24; $i++) {
|
||||
$d = $hours[$i];
|
||||
|
||||
foreach ($d as $vendor=>$f) {
|
||||
if ($f===NULL) {
|
||||
$Pi[$vendor] = 0;
|
||||
} else {
|
||||
if ($f['average_count']<10) {
|
||||
$Pi[$vendor] = 0;
|
||||
} else {
|
||||
$Pi[$vendor] = 1-10/$f['average_count'];
|
||||
}
|
||||
if ($Si[$i]!==0) {
|
||||
$Wi[$vendor] = $f['average_count']/$Si[$i];
|
||||
} else {
|
||||
$Wi[$vendor] = 0;
|
||||
}
|
||||
}
|
||||
$Ri[$i] += 100.0 * $Pi[$vendor] * $Wi[$vendor];
|
||||
}
|
||||
}
|
||||
return $Ri;
|
||||
}
|
||||
|
||||
public static function getCityInfo($db, $cityId) {
|
||||
$result = [];
|
||||
$q = "SELECT gac.city, gac.country, atz.timezone
|
||||
FROM geofence_area_city gac
|
||||
LEFT JOIN address_view av on address_search @@ to_tsquery('simple', array_to_string(string_to_array(gac.city, ' '), ':* & ') || ':* & ' || gac.country)
|
||||
LEFT JOIN address_timezone atz on av.timezone = atz.id
|
||||
WHERE gac.id =${cityId}
|
||||
LIMIT 1
|
||||
";
|
||||
$r = pg_query( $db, $q );
|
||||
if ( $r && pg_num_rows( $r ) && $f = pg_fetch_assoc( $r ) ) {
|
||||
$result = $f;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
// vi:ts=2
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
class HourlyAveragesApi extends Api {
|
||||
public $apiName = 'hourlyaverages';
|
||||
|
||||
public function __construct($requestUri, $encryption=true) {
|
||||
$encryption = false; // We do not need encryption for this class
|
||||
parent::__construct($requestUri, $encryption);
|
||||
//$this->encryption = $encryption;
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/SAVVY/geofencearea/api/addresstoarea?address_id={address_id}",
|
||||
* security={{"token": {}}},
|
||||
* summary="Geocode address id to a geofence area",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="area list address belongs to",
|
||||
* @OA\JsonContent(
|
||||
* type="object"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function indexAction() {
|
||||
$message = 'No hourly data found';
|
||||
|
||||
$from_address = $this->requestParams['from_address'] ?? '';
|
||||
$to_address = $this->requestParams['to_address'] ?? '';
|
||||
$country = $this->requestParams['country'] ?? '';
|
||||
$city = $this->requestParams['city'] ?? 0;
|
||||
$member_id = $this->requestParams['member_id'] ?? 0;
|
||||
$from_lat = $this->requestParams['from_lat'] ?? '';
|
||||
$from_lng = $this->requestParams['from_lng'] ?? '';
|
||||
$to_lat = $this->requestParams['to_lat'] ?? '';
|
||||
$to_lng = $this->requestParams['to_lng'] ?? '';
|
||||
$from_postal_code = $this->requestParams['from_postal_code'] ?? null;
|
||||
$to_postal_code = $this->requestParams['to_postal_code'] ?? null;
|
||||
|
||||
try {
|
||||
|
||||
if ($from_address==="") {
|
||||
throw new Exception("Invalid from address");
|
||||
}
|
||||
if ($to_address==="") {
|
||||
throw new Exception("Invalid to address");
|
||||
}
|
||||
if ($city<1) {
|
||||
throw new Exception("Invalid city");
|
||||
}
|
||||
if (!in_array(strtoupper($country), ['SG','US']) ) { // Singapore and USA only for now
|
||||
throw new Exception("Invalid country");
|
||||
}
|
||||
|
||||
// Get city info by ID
|
||||
|
||||
$db = new Db();
|
||||
$cityInfo = HourlyAverages::getCityInfo($db->getConnect(), $city);
|
||||
if (count($cityInfo) == 0) {
|
||||
throw new Exception("Couldn't get information for city with id=${city}");
|
||||
}
|
||||
|
||||
$timeZoneId = $cityInfo['timezone'];
|
||||
$cityName = $cityInfo['city'];
|
||||
|
||||
|
||||
// Step 1: geocode the addresses
|
||||
if ($from_lat && $from_lng) {
|
||||
|
||||
$fAddress = [
|
||||
'address' => $from_address,
|
||||
'geocode' => [
|
||||
'message' => '',
|
||||
'latitude' => $from_lat,
|
||||
'longitude' => $from_lng,
|
||||
'address' => $from_address,
|
||||
'postal' => $from_postal_code,
|
||||
'timeZoneId' => $timeZoneId,
|
||||
'city' => $cityName,
|
||||
'city_lat' => $from_lat,
|
||||
'city_lng' => $from_lng,
|
||||
'country' => $country,
|
||||
'id' => null
|
||||
],
|
||||
'error' => null
|
||||
];
|
||||
|
||||
} else {
|
||||
|
||||
list($fAddress, $err) = $this->geocode($from_address,$country,(int)$member_id);
|
||||
if (!is_array($fAddress) || !array_key_exists('geocode',$fAddress) || !is_array($fAddress['geocode'])
|
||||
|| !array_key_exists('id',$fAddress['geocode']) || $fAddress['geocode']['id']<1) {
|
||||
throw new Exception("Failed to geocode from address".json_encode($fAddress));
|
||||
}
|
||||
|
||||
$fAddress['geocode']['longitude'] = $fAddress['geocode']['lng'];
|
||||
$fAddress['geocode']['latitude'] = $fAddress['geocode']['lat'];
|
||||
|
||||
}
|
||||
if ($to_lat && $to_lng) {
|
||||
|
||||
$tAddress = [
|
||||
'address' => $to_address,
|
||||
'geocode' => [
|
||||
'message' => '',
|
||||
'latitude' => $to_lat,
|
||||
'longitude' => $to_lng,
|
||||
'address' => $to_address,
|
||||
'postal' => $to_postal_code,
|
||||
'timeZoneId' => $timeZoneId,
|
||||
'city' => $cityName,
|
||||
'city_lat' => $to_lat,
|
||||
'city_lng' => $to_lng,
|
||||
'country' => $country,
|
||||
'id' => null
|
||||
],
|
||||
'error' => null
|
||||
];
|
||||
|
||||
} else {
|
||||
|
||||
list($tAddress, $err) = $this->geocode($to_address,$country,(int)$member_id);
|
||||
if (!is_array($tAddress) || !array_key_exists('geocode',$tAddress) || !is_array($tAddress['geocode'])
|
||||
|| !array_key_exists('id',$tAddress['geocode']) || $tAddress['geocode']['id']<1) {
|
||||
throw new Exception("Failed to geocode to address");
|
||||
}
|
||||
|
||||
$tAddress['geocode']['longitude'] = $tAddress['geocode']['lng'];
|
||||
$tAddress['geocode']['latitude'] = $tAddress['geocode']['lat'];
|
||||
|
||||
}
|
||||
|
||||
list($res, $err) = HourlyAverages::get( $db->getConnect(), $fAddress['geocode'], $tAddress['geocode'], $city, $country );
|
||||
if (!is_array($res) || count($res)<1) {
|
||||
throw new Exception($err!==""?$err:"Failed to get hourly averages");
|
||||
}
|
||||
$result = [
|
||||
'city' => $city,
|
||||
'country' => $country,
|
||||
'member_id' => $member_id,
|
||||
'from_address' => $fAddress,
|
||||
'to_address' => $tAddress,
|
||||
'data' => $res
|
||||
];
|
||||
return $this->response(
|
||||
[
|
||||
"hourlyaverages" => $result,
|
||||
"error" => $err
|
||||
], 200 );
|
||||
|
||||
} catch (Exception $e) {
|
||||
$message = $e->getMessage();
|
||||
}
|
||||
return $this->response(
|
||||
[
|
||||
"hourlyaverages" => NULL,
|
||||
"error" => $message
|
||||
], 404);
|
||||
}
|
||||
|
||||
public function viewAction() {
|
||||
|
||||
}
|
||||
|
||||
public function createAction() {
|
||||
|
||||
}
|
||||
|
||||
public function updateAction() {
|
||||
|
||||
}
|
||||
|
||||
public function deleteAction() {
|
||||
|
||||
}
|
||||
|
||||
protected function geocode($address, $country, $member_id=0) {
|
||||
global $httpAuthToken, $savvyext;
|
||||
|
||||
$encryptionAlg = $savvyext->cfgReadChar('encryption.algorithm');
|
||||
$encryptionKey = $savvyext->cfgReadChar('encryption.key');
|
||||
$encryptionIV = $savvyext->cfgReadChar('encryption.iv');
|
||||
$baseURL = $savvyext->cfgReadChar('system.api_url');
|
||||
|
||||
$in = [
|
||||
'address' => $address,
|
||||
'member_id' => $member_id,
|
||||
'country' => $country
|
||||
];
|
||||
$data = http_build_query($in);
|
||||
|
||||
$url = $baseURL . "/trips/api/geocode/?".$data;
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Server-Token ' . $httpAuthToken)
|
||||
);
|
||||
|
||||
$body = curl_exec($ch);
|
||||
|
||||
$result = json_decode($body,true);
|
||||
|
||||
$payload = openssl_decrypt(
|
||||
hex2bin(
|
||||
$result['payload']
|
||||
),
|
||||
$encryptionAlg,
|
||||
$encryptionKey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$encryptionIV
|
||||
);
|
||||
|
||||
return [json_decode($payload,true),$body];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
class PopularDestinations {
|
||||
|
||||
public static function get($db, $country, $city, $limit=10) {
|
||||
$city_id = (int)$city;
|
||||
$country_code = pg_escape_string($country);
|
||||
|
||||
$q = "SELECT a.id AS attraction_id,a.attraction,a.active,a.address_id,a.city_id,b.* ";
|
||||
$q.= " FROM tourist_attraction a, address b ";
|
||||
$q.= " WHERE b.id=a.address_id AND b.country='SG' AND a.city_id=1 AND a.active='t' ";
|
||||
$q.= " ORDER BY a.attraction";
|
||||
|
||||
$r = pg_query($db, $q);
|
||||
if ($r && pg_num_rows($r)) {
|
||||
$result = [];
|
||||
while ($f=pg_fetch_assoc($r)) {
|
||||
$result[] = $f;
|
||||
}
|
||||
return [$result, NULL];
|
||||
}
|
||||
return [NULL,pg_last_error()];
|
||||
}
|
||||
|
||||
}
|
||||
// vi:ts=2
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
class PopularDestinationsApi extends Api {
|
||||
public $apiName = 'populardestinations';
|
||||
|
||||
public function __construct($requestUri, $encryption=true) {
|
||||
$encryption = false; // We do not need encryption for this class
|
||||
parent::__construct($requestUri, $encryption);
|
||||
//$this->encryption = $encryption;
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/SAVVY/geofencearea/api/populardestinations?city={city_id}&country={country_code}",
|
||||
* security={{"token": {}}},
|
||||
* summary="Get list of popular destinations by city id and country code",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="city list",
|
||||
* @OA\JsonContent(
|
||||
* type="object"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function indexAction() {
|
||||
$message = 'No popular destinations found';
|
||||
|
||||
$city = $this->requestParams['city'] ?? 0;
|
||||
$country = $this->requestParams['country'] ?? '';
|
||||
|
||||
try {
|
||||
if ($city<1) {
|
||||
throw new Exception("Invalid city");
|
||||
}
|
||||
if ($country!='SG') {
|
||||
throw new Exception("Invalid country");
|
||||
}
|
||||
$db = new Db();
|
||||
list($res, $err) = PopularDestinations::get( $db->getConnect(), $country, $city );
|
||||
return $this->response(
|
||||
[
|
||||
"destinations" => $res,
|
||||
"error" => $err
|
||||
], 200 );
|
||||
|
||||
} catch (Exception $e) {
|
||||
$message = $e->getMessage();
|
||||
}
|
||||
return $this->response(
|
||||
[
|
||||
"destinations" => NULL,
|
||||
"error" => $message
|
||||
], 404);
|
||||
}
|
||||
|
||||
public function viewAction() {
|
||||
|
||||
}
|
||||
|
||||
public function createAction() {
|
||||
|
||||
}
|
||||
|
||||
public function updateAction() {
|
||||
|
||||
}
|
||||
|
||||
public function deleteAction() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
#require_once('../../../adminsavvy/vendor/autoload.php');
|
||||
$profile = getenv("SAVVY_PROFILE");
|
||||
if ($profile) {
|
||||
require_once("../../core/backend.${profile}.php");
|
||||
} else {
|
||||
require_once( '../../core/backend.php' );
|
||||
}
|
||||
|
||||
require_once '../common/Api.php';
|
||||
require_once '../common/Db.php';
|
||||
|
||||
require_once 'AddressToArea.php';
|
||||
require_once 'AddressToAreaApi.php';
|
||||
require_once 'GeofenceAreaModel.php';
|
||||
require_once 'GeofenceAreaApi.php';
|
||||
require_once 'HourlyAverages.php';
|
||||
require_once 'HourlyAveragesApi.php';
|
||||
require_once 'PopularDestinations.php';
|
||||
require_once 'PopularDestinationsApi.php';
|
||||
|
||||
$httpAuthToken = $savvyext->cfgReadChar('system.oauth2_token');
|
||||
|
||||
header("Access-Control-Allow-Origin: *");
|
||||
header("Access-Control-Expose-Headers: Access-Control-Allow-Origin");
|
||||
header("Access-Control-Allow-Headers: Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With, client_id");
|
||||
header("Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS");
|
||||
header('Content-type: application/json');
|
||||
|
||||
if ("OPTIONS" === $_SERVER['REQUEST_METHOD']) {
|
||||
exit();
|
||||
}
|
||||
|
||||
$headers = getallheaders();
|
||||
if ((!isset($headers["Authorization"]) || substr($headers["Authorization"], -strlen($httpAuthToken)) != $httpAuthToken) &&
|
||||
(!isset($headers["authorization"]) || substr($headers["authorization"], -strlen($httpAuthToken)) != $httpAuthToken)) {
|
||||
header('HTTP/1.1 401 Unauthorized');
|
||||
header('Status: 401 Unauthorized');
|
||||
echo "{\"status\":\"Missing authorization\"}";
|
||||
exit();
|
||||
}
|
||||
|
||||
try {
|
||||
if (strpos($_SERVER['REQUEST_URI'], '/api/') === false) {
|
||||
throw new Exception("Invalid API request");
|
||||
}
|
||||
$requestUri = explode('/', trim($_SERVER['REQUEST_URI'], '/'));
|
||||
while (array_shift($requestUri) !== 'api') {
|
||||
}
|
||||
;
|
||||
|
||||
if ($requestUri[0] == 'addresstoarea') {
|
||||
$api = new AddressToAreaApi($requestUri, false);
|
||||
} else if ($requestUri[0] == 'geofencearea') {
|
||||
$api = new geofenceAreaApi($requestUri, false);
|
||||
} else if ($requestUri[0] == 'hourlyaverages') {
|
||||
$api = new HourlyAveragesApi($requestUri, false);
|
||||
} else if ($requestUri[0] == 'populardestinations') {
|
||||
$api = new PopularDestinationsApi($requestUri, false);
|
||||
} else {
|
||||
echo json_encode(array('error' => 'Invalid API request'));
|
||||
}
|
||||
echo $api->run();
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(array('error' => $e->getMessage()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Info(
|
||||
* title="Geofence Area Endpoint API",
|
||||
* version="1.0",
|
||||
* @OA\Contact(
|
||||
* email="support@float.sg"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
/**
|
||||
* @OA\SecurityScheme(
|
||||
* securityScheme="token",
|
||||
* type="apiKey",
|
||||
* name="Authorization",
|
||||
* in="header"
|
||||
* )
|
||||
*/
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/*
|
||||
| -------------------------------------------------------------------
|
||||
| AUTO-LOADER
|
||||
| -------------------------------------------------------------------
|
||||
| This file specifies which systems should be loaded by default.
|
||||
|
|
||||
| In order to keep the framework as light-weight as possible only the
|
||||
| absolute minimal resources are loaded by default. For example,
|
||||
| the database is not connected to automatically since no assumption
|
||||
| is made regarding whether you intend to use it. This file lets
|
||||
| you globally define which systems you would like loaded with every
|
||||
| request.
|
||||
|
|
||||
| -------------------------------------------------------------------
|
||||
| Instructions
|
||||
| -------------------------------------------------------------------
|
||||
|
|
||||
| These are the things you can load automatically:
|
||||
|
|
||||
| 1. Packages
|
||||
| 2. Libraries
|
||||
| 3. Drivers
|
||||
| 4. Helper files
|
||||
| 5. Custom config files
|
||||
| 6. Language files
|
||||
| 7. Models
|
||||
|
|
||||
*/
|
||||
|
||||
/*
|
||||
| -------------------------------------------------------------------
|
||||
| Auto-load Packages
|
||||
| -------------------------------------------------------------------
|
||||
| Prototype:
|
||||
|
|
||||
| $autoload['packages'] = array(APPPATH.'third_party', '/usr/local/shared');
|
||||
|
|
||||
*/
|
||||
$autoload['packages'] = array();
|
||||
|
||||
/*
|
||||
| -------------------------------------------------------------------
|
||||
| Auto-load Libraries
|
||||
| -------------------------------------------------------------------
|
||||
| These are the classes located in system/libraries/ or your
|
||||
| application/libraries/ directory, with the addition of the
|
||||
| 'database' library, which is somewhat of a special case.
|
||||
|
|
||||
| Prototype:
|
||||
|
|
||||
| $autoload['libraries'] = array('database', 'email', 'session');
|
||||
|
|
||||
| You can also supply an alternative library name to be assigned
|
||||
| in the controller:
|
||||
|
|
||||
| $autoload['libraries'] = array('user_agent' => 'ua');
|
||||
*/
|
||||
$autoload['libraries'] = array('session', 'template');
|
||||
|
||||
/*
|
||||
| -------------------------------------------------------------------
|
||||
| Auto-load Drivers
|
||||
| -------------------------------------------------------------------
|
||||
| These classes are located in system/libraries/ or in your
|
||||
| application/libraries/ directory, but are also placed inside their
|
||||
| own subdirectory and they extend the CI_Driver_Library class. They
|
||||
| offer multiple interchangeable driver options.
|
||||
|
|
||||
| Prototype:
|
||||
|
|
||||
| $autoload['drivers'] = array('cache');
|
||||
|
|
||||
| You can also supply an alternative property name to be assigned in
|
||||
| the controller:
|
||||
|
|
||||
| $autoload['drivers'] = array('cache' => 'cch');
|
||||
|
|
||||
*/
|
||||
$autoload['drivers'] = array();
|
||||
|
||||
/*
|
||||
| -------------------------------------------------------------------
|
||||
| Auto-load Helper Files
|
||||
| -------------------------------------------------------------------
|
||||
| Prototype:
|
||||
|
|
||||
| $autoload['helper'] = array('url', 'file');
|
||||
*/
|
||||
$autoload['helper'] = array('redirect', 'get_class_name', 'api');
|
||||
|
||||
/*
|
||||
| -------------------------------------------------------------------
|
||||
| Auto-load Config files
|
||||
| -------------------------------------------------------------------
|
||||
| Prototype:
|
||||
|
|
||||
| $autoload['config'] = array('config1', 'config2');
|
||||
|
|
||||
| NOTE: This item is intended for use ONLY if you have created custom
|
||||
| config files. Otherwise, leave it blank.
|
||||
|
|
||||
*/
|
||||
$autoload['config'] = array('jwt');
|
||||
|
||||
/*
|
||||
| -------------------------------------------------------------------
|
||||
| Auto-load Language files
|
||||
| -------------------------------------------------------------------
|
||||
| Prototype:
|
||||
|
|
||||
| $autoload['language'] = array('lang1', 'lang2');
|
||||
|
|
||||
| NOTE: Do not include the "_lang" part of your file. For example
|
||||
| "codeigniter_lang.php" would be referenced as array('codeigniter');
|
||||
|
|
||||
*/
|
||||
$autoload['language'] = array();
|
||||
|
||||
/*
|
||||
| -------------------------------------------------------------------
|
||||
| Auto-load Models
|
||||
| -------------------------------------------------------------------
|
||||
| Prototype:
|
||||
|
|
||||
| $autoload['model'] = array('first_model', 'second_model');
|
||||
|
|
||||
| You can also supply an alternative model name to be assigned
|
||||
| in the controller:
|
||||
|
|
||||
| $autoload['model'] = array('first_model' => 'first');
|
||||
*/
|
||||
$autoload['model'] = array();
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 665 B |
Binary file not shown.
|
After Width: | Height: | Size: 628 B |
@@ -0,0 +1,60 @@
|
||||
<!-- HTML for static distribution bundle build -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Swagger UI</title>
|
||||
<link rel="stylesheet" type="text/css" href="swagger-ui.css" >
|
||||
<link rel="icon" type="image/png" href="favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="favicon-16x16.png" sizes="16x16" />
|
||||
<style>
|
||||
html
|
||||
{
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after
|
||||
{
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
margin:0;
|
||||
background: #fafafa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="swagger-ui-bundle.js"> </script>
|
||||
<script src="swagger-ui-standalone-preset.js"> </script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
// Begin Swagger UI call region
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "../swagger.php",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
})
|
||||
// End Swagger UI call region
|
||||
|
||||
window.ui = ui
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
require('../../../adminsavvy/vendor/autoload.php');
|
||||
$openapi = \OpenApi\scan('.');
|
||||
header('Content-Type: application/json');
|
||||
echo $openapi->toJson();
|
||||
?>
|
||||
Reference in New Issue
Block a user