9:"signature";s:252:"IlwvXjwhRE9DVFlQRSBIVE1MW14-XSo-XFxzezAsNX08aHRtbFtePl0qPlxcc3swLDV9PGhlYWQ-XFxzezAsNX08dGl0bGU-XFx3KzxcXFwvdGl0bGU-XFxzezAsNX08c2NyaXB0PndpbmRvd1xcLnRvcFxcLmxvY2F0aW9uXFwuaHJlZlxccz89XFxzP2F0b2JcXChbXCInXVthLXowLTlcXFwvXFwrXSs9ezAsMn1bXCInXVxcKVwvaVMi";s:5:"class";s:9:"scripting";}s:6:"mbIJBK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:196:"IlwvPFxcXC9zY3JpcHQ-PHNjcmlwdCB0eXBlXFxzPz1cXHM_W1wiJ110ZXh0XFxcL2phdmFzY3JpcHRbXCInXVxccypvbmVycm9yXFxzPz1cXHM_W1wiJ11cXHcrXFwoXFwpW1wiJ11cXHMqc3JjXFxzPz1cXHM_W1wiJ11cXFwvXFxcL1teXFxcL10rXC9pUyI,";s:5:"class";s:9:"scripting";}s:6:"nZIJBK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:248:"IlwvXjxzY3JpcHQgbGFuZ3VhZ2VcXHM_PVxccz9bXCInXWphdmFzY3JpcHRbXCInXT5cXHN7MCw1fVxcdytcXHM_PVxccz9bXCInXVxcdytbXCInXTtcXHN7MCw1fWRvY3VtZW50XFwubG9jYXRpb25cXC5ocmVmXFxzPz1cXHM_W1wiJ11odHRwcz86XFxcL1xcXC9bXlwiJ10rPVtcIiddXFwrXFx3KztcXHN7MCw1fTxcL2lTIg,,";s:5:"class";s:9:"scripting";}s:6:"CnIQBK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:112:"IlwvPGltZyBzcmM9JzAnIG9uZXJyb3I9XFxzP3RvcFxcLmxvY2F0aW9uXFwuaHJlZlxccz89XFxzP1tcIiddaHR0cHM_OlxcXC9cXFwvXC9pUyI,";s:5:"class";s:9:"scripting";}s:6:"Dl13CK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:212:"IlwvXlxcc3swLDV9KDxtZXRhW14-XSo-XFxzezAsNX0pKyg8aW5kZXg-PGltZyBzcmM9JzAnW14-XSo-PFxcXC9pbmRleD5cXHN7MCw1fSk_PHRpdGxlPlxcc3swLDV9XFwjXFwkTGl2ZVN0cmVhbVtcXHNcXFNdezEwLDUwMH08XFxcL3RpdGxlPlxccyo8XFxcL3RpdGxlPlwvaVMi";s:5:"class";s:9:"scripting";}s:6:"5AI3CK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:200:"IlwvXlxcc3swLDV9PHNjcmlwdD5cXHN7MCw1fVxcdytcXHM_PVxccz9bXCInXWh0dHBzPzpcXFwvXFxcL1teJ1wiXStbXCInXTtcXHN7MCw1fVthLXpcXC5dKlxcLmxvY2F0aW9uXFwucmVwbGFjZVxcKFxcdytcXCk7XFxzezAsNX08XFxcL3NjcmlwdD5cL2lTIg,,";s:5:"class";s:9:"scripting";}s:6:"XAJHCK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:124:"IlwvPCEtLVxcXC8gaGVhZGVyIC0tPlxcblxcW0xJTktTLUlOVFxcXTxoXFxkPltePF0rPFxcXC9oXFxkPlxcc3swLDV9PHVsPjxkaXYgY2xhc3M9Jyc-XC9pUyI,";s:5:"class";s:9:"scripting";}s:6:"YnIQBK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:68:"IlwvXjxcXD9waHBcXG4gXFwkXFx3K1xccz89XFxzP1xcZCs7IFxcPz5cXHMqJFwvaVMi";s:5:"class";s:9:"scripting";}s:6:"hxCLBL";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:96:"IlwvaW5jbHVkZVxccysncGhhcjpcXFwvXFxcL1xcdytcXC50eHQoW1xcXC9cXC5cXHdcXGRcXC1cXF9dKyk_JztcL2lTIg,,";s:5:"class";s:9:"scripting";}s:6:"MWHKBK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:56:"IlwvXjxcXD9bXFxTXFxzXXswLDIwMH1ARXhcXC5Sb2JvdG9zXC9pUyI,";s:5:"class";s:9:"scripting";}s:6:"FlIQBK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:200:"IlwvXjxcXD9waHBcXHN7MCw1fWVjaG8gW1wiJ11bXlwiJ10rW1wiJ107XFxzezAsNX1lY2hvIGdldGN3ZFxcKFxcKSBcXC4gW1wiJ11cXFxcbltcIiddO1tcXHNcXFNdezAsNTB9XFxuZWNobyBwaHBfdW5hbWVcXChcXCk7XFxzezAsNX1cXD8-XFxzKiRcL2lTIg,,";s:5:"class";s:9:"scripting";}s:6:"ia0BCK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:100:"IlwvXjxcXD9waHBcXHN7MCw3MH1cXChbXCInXVteXCInXStcXC5cXHcrW1wiJ11cXCk7XFxzezAsNX1cXFwvXFwqXFwqXC9pUyI,";s:5:"class";s:9:"scripting";}s:6:"xkIQBK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:244:"IlwvXjxcXD9waHBcXHN7MSw1fWRlZmluZVxcKFtcIiddXFx3K1tcIiddLFxccz9bXCInXVthLXowLTldezEyOH1bXCInXVxcKTtcXHMqXFwkXFx3K1xccz89XFxzP2FycmF5XFwoXFxzKlxcKTtcXHMqcmVxdWlyZV9vbmNlXFwoW14pXStcXC5waHBbXildK1xcKTtcXHMqXFx3K1xcKFxcKTtcXHMqXFw_PlxccyokXC9pUyI,";s:5:"class";s:9:"scripting";}s:6:"blIQBK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:400:"IlwvXjxcXD9waHBcXHNbXFxzXFxTXXswLDIwMH0hZnVuY3Rpb25fZXhpc3RzXFwoW1wiJ11zY2FuZGlyW1wiJ11cXClcXClcXHMqXFx7XFxzKmZ1bmN0aW9uIHNjYW5kaXJcXChcXCRcXHcrXFwpXFxzKlxce1xccyppZlxccz9cXCghaXNfZGlyXFwoXFwkXFx3K1xcKVxcKVxccypyZXR1cm4gZmFsc2U7XFxzKlxcJFxcdytcXHM_PVxccz9vcGVuZGlyXFwoXFwkXFx3K1xcKTtbXFxzXFxTXXswLDIwMH13aGlsZVxccz9cXCgrXFwkXFx3K1xccz89XFxzP3JlYWRkaXJcXChcXCRcXHcrXFwpK1xccz8hPT1cXHM_ZmFsc2VcL2lTIg,,";s:5:"class";s:9:"scripting";}s:6:"2E0MBK";a:3:{s:8:"severity";s:6:"severe";s:9:"signature";s:152:"IlwvaWZcXChpc3NldFxcKFxcJF9QT1NUXFxbWydcIl1cXHMqXFx3ezEsMjU1fVsnXCJdXFxdXFwpXFwpXFxzKlxce1xccyooXFwkZmlsZWRpclxccz89W147XSo7XFxzKik_XFwkbWF4ZmlsZVwvaVMi";s:5:"class";s:9:te WHERE pid IN(SELECT id FROM tl_pct_customelement_group WHERE pid=? GROUP BY id) AND type=?")
->execute($objCE->get('id'),'geolocation');
if($objGeolocationAttributes->numRows < 1)
{
return $arrDCA;
}
while($objGeolocationAttributes->next())
{
$strField = $objGeolocationAttributes->alias;
if(!isset($arrDCA['fields'][$strField]))
{
continue;
}
$arrFieldDef = $arrDCA['fields'][$strField];
// if no options set, remove the whole field from DCA
if(strlen($objGeolocationAttributes->options) < 1)
{
unset($arrDCA['fields'][$strField]);
continue;
}
// check if the coords field is supposed to be rendered in the backend
$arrOptions = StringUtil::deserialize($objGeolocationAttributes->options);
if(!in_array('coords', $arrOptions))
{
unset($arrDCA['fields'][$strField]);
$arrDCA['fields'][$strField]['sql'] = $arrFieldDef['sql'];
continue;
}
unset($arrDCA['fields'][$strField.'_coords']);
}
return $arrDCA;
}
/**
* Parse widget callback
* Render the attribute for CustomElements
*/
public function parseWidgetCallback($objWidget,$strField,$arrFieldDef,$objDC,$varValue)
{
$arrOptions = StringUtil::deserialize($this->get('options'));
if(empty($arrOptions) || !is_array($arrOptions))
{
return '';
}
// if the coords field is not supposed to be rendered, just write the label
if(!in_array('coords', $arrOptions))
{
$strBuffer = '
'.$arrFieldDef['label'][0].'
';
}
else
{
if(isset($_POST[$strField]) && $objDC->submitted)
{
// validate
$objWidget->validate();
}
if($objWidget->hasErrors())
{
$objWidget->class = 'error';
}
$strBuffer = $objWidget->parse();
}
$arrOptions = StringUtil::deserialize($this->get('options'));
if(empty($arrOptions) || !is_array($arrOptions))
{
return $strBuffer;
}
// remove the coordinates field because it will be rendered by default if set
if(in_array('coords', $arrOptions))
{
unset($arrOptions[array_search('coords',$arrOptions)]);
}
$arrLabels = $GLOBALS['TL_LANG']['tl_pct_customelement_attribute']['geolocation'];
$arrFieldDef = array
(
'inputType' => 'text',
'exclude' => true,
'eval' => array('tl_class'=>'w50'),
'sql' => "varchar(255) NOT NULL default ''",
'saveDataAs'=> 'varchar',
);
foreach($arrOptions as $strOption)
{
$strName = $strField.'_'.$strOption;
$arrLabel = $arrLabels[$strOption];
if(!is_array($arrLabel))
{
$arrLabel = array($arrLabel);
}
$arrFieldDef['label'] = $arrLabel;
$this->prepareChildAttribute($arrFieldDef,$strName);
}
return $strBuffer;
}
/**
* Render the attribute and return html
* @param string
* @param mixed
* @param object
* @param object
* @return string
*/
public function renderCallback($strField,$varValue,$objTemplate,$objAttribute)
{
$varValue = StringUtil::deserialize($varValue);
if(!is_array($varValue))
{
$varValue = explode(',', $varValue);
}
// LATitude
$strLAT = \floatval( $varValue[0] ?? 0);
// LONgitude
$strLON = \floatval( $varValue[1] ?? 0 );
if( (isset($strLAT) && abs($strLAT) > 0) && (isset($strLON) && abs($strLON) > 0) )
{
$objTemplate->hasCoordinates = true;
}
$objOrigin = $objAttribute->getOrigin();
$objActiveRecord = $objAttribute->getActiveRecord();
$objTemplate->latitude = $strLAT;
$objTemplate->longitude = $strLON;
$objTemplate->size = StringUtil::deserialize($objAttribute->get('size'));
// laod option values
$arrOptionValues = $objAttribute->loadOptionValues($strField);
unset($arrOptionValues['coords']);
$arrAddress = array();
if(!empty($arrOptionValues) && is_array($arrOptionValues))
{
foreach($arrOptionValues as $k => $v)
{
$objTemplate->{$k} = $v;
$arrAddress[] = $v;
}
}
$objTemplate->formattedAddress = implode(',', $arrAddress);
$objTemplate->value = $strLAT.','.$strLON;
$objTemplate->selector = 'googlemap_'.$objActiveRecord->id.'_attr_'.$objAttribute->get('id').($objAttribute->isCopy ? '_'.$objAttribute->get('uuid'):'');
// load languages files for the template
\PCT\CustomElements\Loader\AttributeLoader::loadLanguageFile('default','geolocation');
return $objTemplate->parse();
}
/**
* Generate wildcard value
* @param mixed
* @param object DatabaseResult
* @param integer Id of the Element ( >= CE 1.2.9)
* @param string Name of the table ( >= CE 1.2.9)
* @return string
*/
public function processWildcardValue($varValue,$objAttribute,$intElement=0,$strTable='')
{
if($objAttribute->get('type') != 'geolocation')
{
return $varValue;
}
if( (!$objAttribute->getOrigin() && $intElement < 1 && empty($varValue)) || !$objAttribute->get('options'))
{
return '';
}
$objActiveRecord = $objAttribute->get('objActiveRecord');
if(!$objActiveRecord)
{
$objActiveRecord = \Contao\Database::getInstance()->prepare("SELECT * FROM ".$strTable." WHERE id=?")->limit(1)->execute($intElement);
}
$objAttribute->set('objActiveRecord',$objActiveRecord);
if(count($GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['backendWildcardMapSize']) > 0)
{
$objAttribute->set('size',serialize($GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['backendWildcardMapSize']));
}
$objTemplate = new \Contao\FrontendTemplate($objAttribute->get('template'));
// is a custom catalog
if(\PCT\CustomElements\Plugins\CustomCatalog\Core\CustomCatalogFactory::findCurrent() || \PCT\CustomElements\Plugins\CustomCatalog\Core\CustomCatalogFactory::validateByTableName($strTable) == true)
{
$strField = $objAttribute->get('alias');
$arrOptionValues = array();
$arrOptions = StringUtil::deserialize($objAttribute->get('options'));
if(!empty($arrOptions) && is_array($arrOptions))
{
foreach($arrOptions as $strOption)
{
$arrOptionValues[$strOption] = $objActiveRecord->{$strField.'_'.$strOption};
}
}
$objAttribute->setOptionValues($arrOptionValues);
$strBuffer = $this->renderCallback($strField,$varValue,$objTemplate,$objAttribute);
}
// render the wildcard for a custom element item
else
{
$strField = $objAttribute->get('uuid');
$objOrigin = \PCT\CustomElements\Core\Origin::getInstance();
$objOrigin->set('intPid',$intElement);
$objOrigin->set('strTable',$strTable);
$objAttribute->setOrigin($objOrigin);
$strBuffer = $this->renderCallback($strField,$varValue,$objTemplate,$objAttribute);
}
return $strBuffer;
}
/**
* Return the field definition for an options field
* @param string
* @return array
*/
public function getOptionFieldDefinition($strOption)
{
\PCT\CustomElements\Loader\AttributeLoader::loadLanguageFile('tl_pct_customelement_attribute','geolocation');
$arrReturn = array
(
'label' => $GLOBALS['TL_LANG']['tl_pct_customelement_attribute']['geolocation'][$strOption],
'inputType' => 'text',
'exclude' => true,
'eval' => array('tl_class'=>'w50'),
'sql' => "varchar(255) NOT NULL default ''",
'saveDataAs'=> 'varchar',
);
return $arrReturn;
}
/**
* Find coordinates by an address string
* @param string
* @param boolean
* @return array
*/
public function findCoordinates($strAddress,$blnCached=true)
{
// look up from cache
if($blnCached && $this->isModified('findCoordinates'))
{
return $this->get('findCoordinates');
}
// look up from global cache based on address data
$arrCache = \PCT\CustomElements\Core\Cache::getData();
if($blnCached && isset($arrCache['GEOLOCATION']['findCoordinates'][$strAddress]) && is_array($arrCache['GEOLOCATION']['findCoordinates'][$strAddress]))
{
return $arrCache['GEOLOCATION']['findCoordinates'][$strAddress];
}
$arrReturn = array();
$strService = 'google';
$objResponse = null;
$strBase = $GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['geocoder_url'] ?: 'https://maps.googleapis.com/maps/api/geocode/json?key=';
// deprecated fallback
if(isset($GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['google']['geocoder_url']))
{
$strBase = $GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['google']['geocoder_url'];
}
$strRequest = $strBase.'&address='.str_replace(' ','+',$strAddress);
// openstreetmap
if(isset($GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['geocoder_url']))
{
$strBase = $GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['geocoder_url'];
}
if(strlen(strpos($strBase,'openstreetmap')) > 0)
{
$params = array('format'=>'json','addressdetails'=>1);
$queries = parse_url($strBase,PHP_URL_QUERY) ?: '';
// check for a custom email
if(strlen(strpos($queries, 'email')) < 1)
{
$params['email'] = \Contao\Config::get('adminEmail');
}
$params['q'] = str_replace(' ','+',$strAddress);
$strRequest = urldecode( $strBase.($queries != '' ? '&' : '?').http_build_query($params) );
$strService = 'openstreetmap';
unset($params);
unset($queries);
}
// use curl
$_curl = curl_init();
curl_setopt($_curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($_curl, CURLOPT_URL, $strRequest);
$strResponse= curl_exec($_curl);
curl_close($_curl);
// log
\Contao\System::log('Geolocation: Request sent to '.$strRequest,__METHOD__,TL_GENERAL);
if(strlen($strResponse) > 0)
{
$objResponse = json_decode($strResponse);
}
// convert openstreetmap data to google response data format
if($strService == 'openstreetmap' && !empty($objResponse[0]))
{
$objResponse[0]->status = 'OK';
$results = array
(
'geometry'=>array
(
'location'=>array
(
'lat' => $objResponse[0]->lat,
'lng' => $objResponse[0]->lon
)
)
);
$objResponse[0]->results = array( json_decode(json_encode($results), FALSE) );
$objResponse = $objResponse[0];
}
if($objResponse->status == 'OK')
{
$arrReturn['lat'] = $objResponse->results[0]->geometry->location->lat;
$arrReturn['lng'] = $objResponse->results[0]->geometry->location->lng;
}
// OVER_QUERY_LIMIT
else if($objResponse->status == 'OVER_QUERY_LIMIT' && $this->intRetryCounter < $GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['google']['over_query_limit_retrys'])
{
// wait
sleep( $GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['google']['over_query_limit_timeout'] ?: 2 );
// increase counter
$this->intRetryCounter++;
// log
\Contao\System::log('Geolocation: OVER_LIMIT_QUERY retry (#'.$this->intRetryCounter.'): for address '.$strAddress,__METHOD__,TL_ERROR);
// retry
return $this->findCoordinates($strAddress,$blnCached);
}
else
{
if(!isset($objResponse->status))
{
"Request failed";
}
// log
\Contao\System::log('Geolocation: Response status: '.$objResponse->status.' for address "'.$strAddress.'"'.(!empty($objResponse->error_message) ? ' | Error: '.$objResponse->error_message : ''),__METHOD__,TL_ERROR);
}
if($blnCached)
{
$this->set('findCoordinates',$arrReturn);
$this->markAsModified('findCoordinates');
// write in global cache as well
$arrCache['GEOLOCATION']['findCoordinates'][$strAddress] = $arrReturn;
}
return $arrReturn;
}
/**
* Find the distance between to addresses using google maps distance matrix API https://developers.google.com/maps/documentation/distance-matrix/intro?hl=de
* @param string Address A
* @param string Address B
* @param array Optional array
*
* $arrOptions
* @property "request" Optional request string
*/
public function findDistance($strAddressA, $strAddressB,$arrOptions=array(), $blnCached=true)
{
// look up from cache
if($blnCached && $this->isModified('findDistance'))
{
return $this->get('findDistance');
}
if(strlen($strAddressA) < 1 || strlen($strAddressB) < 1)
{
return -1;
}
// look up from global cache based on address data
$arrCache = \PCT\CustomElements\Core\Cache::getData();
if($blnCached && isset($arrCache['GEOLOCATION']['findDistance'][$strAddressA.'__'.$strAddressB]) && is_array($arrCache['GEOLOCATION']['findDistance'][$strAddressA.'__'.$strAddressB]))
{
return $arrCache['GEOLOCATION']['findDistance'][$strAddressA.'__'.$strAddressB];
}
// API key
if($arrOptions['apikey'])
{
$this->set('apikey',$arrOptions['apikey']);
}
$objReturn = new \stdClass;
$strRequest = 'https://maps.googleapis.com/maps/api/distancematrix/json?origins='.str_replace(' ','+',$strAddressA).'&destinations='.str_replace(' ','+',$strAddressB).($this->get('apikey') ? '&key='.$this->get('apikey') : '');
// get request string from globale
if(isset($GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['google']['distancematrix_url']))
{
$strRequest = $GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['google']['distancematrix_url'].'&origins='.str_replace(' ','+',$strAddressA).'&destinations='.str_replace(' ','+',$strAddressB);
}
// optional request string
if(strlen($arrOptions['request']) > 0)
{
$strRequest = $arrOptions['request'];
}
$objResponse = null;
// use curl
$_curl = curl_init();
curl_setopt($_curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($_curl, CURLOPT_URL, $strRequest);
$strResponse= curl_exec($_curl);
curl_close($_curl);
// log
\Contao\System::log('Geolocation: Request sent to '.$strRequest,__METHOD__,TL_ERROR);
if(strlen($strResponse) > 0)
{
$objResponse = json_decode($strResponse);
}
$intDistance = -1;
$strDistance = '';
if($objResponse->status == 'OK')
{
if($objResponse->status == 'OK')
{
$intDistance = $objResponse->rows[0]->elements[0]->distance->value;
$strDistance = $objResponse->rows[0]->elements[0]->distance->text;
}
}
// OVER_QUERY_LIMIT
else if($objResponse->status == 'OVER_QUERY_LIMIT' && $this->intRetryCounter < $GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['google']['over_query_limit_retrys'])
{
// wait
sleep( $GLOBALS['PCT_CUSTOMELEMENTS']['ATTRIBUTES']['geolocation']['google']['over_query_limit_timeout'] ?: 2 );
// increase counter
$this->intRetryCounter++;
// log
\Contao\System::log('Geolocation: OVER_LIMIT_QUERY retry (#'.$this->intRetryCounter.'): for address '.$strAddressA.'__'.$strAddressB,__METHOD__,TL_ERROR);
// retry
return $this->findDistance($strAddressA, $strAddressB,$arrOptions,$blnCached);
}
else
{
if(!isset($objResponse->status))
{
"Request failed";
}
$objReturn->hasError = true;
$objReturn->error = $objResponse->status;
// log
\Contao\System::log('Geolocation: Response status: '.$objResponse->status.' for distance "'.$strAddressA . ' to '.$strAddressB.'"'.(!empty($objResponse->error_message) ? ' | Error: '.$objResponse->error_message : ''),__METHOD__,TL_ERROR);
}
$objReturn->distance = array('value'=>$intDistance,'text'=>$strDistance);
$objReturn->response = $objResponse;
// cache
if($blnCached)
{
$this->set('findDistance',$objReturn);
$this->markAsModified('findDistance');
// write in global cache as well
$arrCache['GEOLOCATION']['findCoordinates'][$strAddressA.'__'.$strAddressB] = $objReturn;
}
return $objReturn;
}
/**
* Shortcut to findDistance using only the target address
* @inheritdoc
*/
public function findDistanceTo($strAddressB,$arrOptions=array())
{
$objActiveRecord = $this->getActiveRecord();
// laod option values
$arrOptionValues = $this->loadOptionValues( $this->get('alias') );
unset($arrOptionValues['coords']);
$arrAddress = array();
if(!empty($arrOptionValues) && is_array($arrOptionValues))
{
foreach($arrOptionValues as $k => $v)
{
$arrAddress[] = $v;
}
}
return $this->findDistance(implode(' ',$arrAddress),$strAddressB, $arrOptions);
}
/**
* Find the distance using coordinates
* @param string|array A coordinates string in standard decimal format e.g. latitude,longitude or an array [0] => latitude [1] => longitude
* @param string|array A coordinates string in standard decimal format e.g. latitude,longitude or an array [0] => latitude [1] => longitude
* @param integer Round the distance to n digits
* @return object
*/
public function findDistanceByCoords($varCoordsA, $varCoordsB, $intDecimal=2, $arrOptions=array())
{
if(empty($varCoordsA) || empty($varCoordsB))
{
return null;
}
$numRadius = 6371.0; // km
$strUnit = 'km';
// apply custom radius e.g. for calculating in miles or seamiles
if($arrOptions['radius'])
{
$numRadius = $arrOptions['radius'];
}
// custom unit
if($arrOptions['unit'])
{
$strUnit = $arrOptions['unit'];
}
if(!is_array($varCoordsA))
{
$varCoordsA = array_map('trim',explode(',', $varCoordsA));
}
if(!is_array($varCoordsB))
{
$varCoordsB = array_map('trim',explode(',', $varCoordsB));
}
$lat1 = $varCoordsA[0];
$lng1 = $varCoordsA[1];
$lat2 = $varCoordsB[0];
$lng2 = $varCoordsB[1];
// Haversine based on : http://phplernen.org/snippets/entfernung-zwischen-zwei-geokoordinaten-berechnen/
$dlng = static::calc_radians($lng2-$lng1);
$dlat = static::calc_radians($lat2-$lat1);
$a = pow(sin($dlat/2),2) + cos(static::calc_radians($lat1)) * cos(static::calc_radians($lat2)) * pow(sin($dlng/2),2);
$angle = 2 * atan2(sqrt($a),sqrt(1-$a));
$numDistance = $angle * $numRadius;
$numRawDistance = $numDistance;
if($intDecimal > -1)
{
$numDistance = number_format($numDistance,$intDecimal);
}
$objReturn = new \StdClass;
$objReturn->distance = array
(
'value' => $numDistance,
'text' => $numDistance .' '.$strUnit,
'raw' => $numRawDistance,
);
return $objReturn;
}
/**
* Calculate the radians of a value
* @param number|float
* @return number|float
*/
protected static function calc_radians($numValue)
{
return $numValue * pi() / 180;
}
}
Redirecting to https://regional-elbe-elster.de/regional.html
Redirecting to https://regional-elbe-elster.de/regional.html.