File: /var/www/vhost/disk-apps/agile-selling-wpb/vendor/cornford/googlmapper/src/Mapper.php
<?php
namespace Cornford\Googlmapper;
use Cornford\Googlmapper\Contracts\MappingInterface;
use Cornford\Googlmapper\Exceptions\MapperArgumentException;
use Cornford\Googlmapper\Exceptions\MapperException;
use Cornford\Googlmapper\Exceptions\MapperInstanceException;
use Cornford\Googlmapper\Exceptions\MapperSearchException;
use Cornford\Googlmapper\Exceptions\MapperSearchKeyException;
use Cornford\Googlmapper\Exceptions\MapperSearchLimitException;
use Cornford\Googlmapper\Exceptions\MapperSearchResponseException;
use Cornford\Googlmapper\Exceptions\MapperSearchResultException;
use Cornford\Googlmapper\Exceptions\MapperSearchResultMalformedException;
use Cornford\Googlmapper\Models\Location;
use Cornford\Googlmapper\Models\Map;
use Cornford\Googlmapper\Models\Streetview;
use Exception;
class Mapper extends MapperBase implements MappingInterface
{
private const GOOGLE_RESPONSE_OK = 'OK';
private const GOOGLE_RESPONSE_ZERO_RESULTS = 'ZERO_RESULTS';
private const GOOGLE_RESPONSE_QUERY_LIMIT = 'OVER_QUERY_LIMIT';
private const GOOGLE_RESPONSE_DENIED = 'REQUEST_DENIED';
private const GOOGLE_RESPONSE_INVALID = 'INVALID_REQUEST';
private const GOOGLE_RESPONSE_UNKNOWN = 'UNKNOWN_ERROR';
/**
* Renders and returns Google Map code.
*
* @param int $item
*
* @return string
*/
public function render($item = -1)
{
if (!$this->isEnabled()) {
return;
}
return $this->view->make('googlmapper::mapper')
->withView($this->view)
->withOptions($this->generateRenderOptions($item))
->withItems($item > -1 ? [$item => $this->getItem($item)] : $this->getItems())
->render();
}
/**
* Renders and returns Google Map javascript code.
*
* @return string
*/
public function renderJavascript()
{
if (!$this->isEnabled()) {
return;
}
return $this->view->make('googlmapper::javascript')
->withView($this->view)
->withOptions($this->generateRenderOptions())
->render();
}
/**
* Generates the render options for Google Map.
*
* @param int $item
*
* @return string
*/
protected function generateRenderOptions($item = -1)
{
$options = $this->getOptions();
foreach (($item > -1 ? [$this->getItem($item)] : $this->getItems()) as $model) {
foreach ($model->getOptions() as $key => $option) {
if (array_key_exists($key, $this->getOptions()) && $this->getOptions()[$key] !== $option) {
$options[$key] = $option;
}
}
}
return $options;
}
/**
* Search for a location against Google Maps Api.
*
* @param string $location
*
* @return mixed
*/
protected function searchLocation($location)
{
$request = file_get_contents(
sprintf(
'https://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false&key=%s',
urlencode($location),
$this->getKey()
)
);
return json_decode($request);
}
/**
* Locate a location and return a Location instance.
*
* @param string $location
*
* @throws MapperArgumentException
* @throws MapperSearchException
* @throws MapperSearchResponseException
* @throws MapperSearchResultException
* @throws MapperSearchKeyException
* @throws MapperSearchLimitException
* @throws MapperException
*
* @return Location
*/
public function location($location)
{
$location = strip_tags($location);
if (empty($location)) {
throw new MapperArgumentException('Invalid location search term provided.');
}
try {
$result = $this->searchLocation($location);
} catch (Exception $exception) {
throw new MapperSearchException('Unable to perform location search, the error was:' .
' "' . $exception->getMessage() . '".');
}
if (
isset($result->status) &&
$result->status == self::GOOGLE_RESPONSE_DENIED &&
property_exists($result, 'error_message') &&
$result->error_message == 'The provided API key is invalid.'
) {
throw new MapperSearchKeyException('Unable to perform location search, provided API key is invalid.');
}
if (isset($result->status) && $result->status == self::GOOGLE_RESPONSE_QUERY_LIMIT) {
throw new MapperSearchLimitException('Unable to perform location search, your API key is over your quota.');
}
if (
isset($result->status) &&
in_array(
$result->status,
[
self::GOOGLE_RESPONSE_DENIED,
self::GOOGLE_RESPONSE_INVALID,
self::GOOGLE_RESPONSE_UNKNOWN
]
)
) {
throw new MapperSearchResponseException('An error occurred performing the location search, the error was:' .
' "' . (property_exists($result, 'error_message') ? $result->error_message : 'Unknown') . '".');
}
if (
(isset($result->status) && $result->status == self::GOOGLE_RESPONSE_ZERO_RESULTS) ||
!isset($result->results) ||
(isset($result->results) && count($result->results) == 0)
) {
throw new MapperSearchResultException('No results found for the location search.');
}
if (
!isset($result->results[0]->formatted_address) ||
!isset($result->results[0]->address_components[0]->types) ||
!isset($result->results[0]->geometry->location->lat) ||
!isset($result->results[0]->geometry->location->lng) ||
!isset($result->results[0]->place_id) ||
isset($result->status) && $result->status != self::GOOGLE_RESPONSE_OK
) {
throw new MapperSearchResultMalformedException('The location search return invalid result data.');
}
$postalCode = null;
foreach ($result->results[0]->address_components as $addressComponent) {
if (count($addressComponent->types) > 0 && $addressComponent->types[0] == 'postal_code') {
$postalCode = $addressComponent->long_name;
}
}
return new Location([
'mapper' => $this,
'search' => $location,
'address' => $result->results[0]->formatted_address,
'postalCode' => $postalCode,
'type' => ($result->results[0]->address_components[0]->types[0] ?? null),
'latitude' => $result->results[0]->geometry->location->lat,
'longitude' => $result->results[0]->geometry->location->lng,
'placeId' => $result->results[0]->place_id,
]);
}
/**
* Add a new map.
*
* @param float $latitude
* @param float $longitude
* @param array $options
*
* @return self
*/
public function map($latitude, $longitude, array $options = [])
{
$parameters = array_replace_recursive(
$this->getOptions(),
[
'latitude' => $latitude,
'longitude' => $longitude,
'map' => 'map_' . count($this->getItems())
],
$options
);
$item = new Map($parameters);
$this->addItem($item);
return $this;
}
/**
* Add a new street view map.
*
* @param float $latitude
* @param float $longitude
* @param int $heading
* @param int $pitch
* @param array $options
*
* @return self
*/
public function streetview($latitude, $longitude, $heading, $pitch, array $options = [])
{
$parameters = array_replace_recursive(
$this->getOptions(),
[
'latitude' => $latitude,
'longitude' => $longitude,
'heading' => $heading,
'pitch' => $pitch,
'map' => 'map_' . count($this->getItems())
],
$options
);
$item = new Streetview($parameters);
$this->addItem($item);
return $this;
}
/**
* Add a new map marker.
*
* @param float $latitude
* @param float $longitude
* @param array $options
*
* @throws MapperException
*
* @return self
*/
public function marker($latitude, $longitude, array $options = [])
{
$items = $this->getItems();
if (empty($items)) {
throw new MapperInstanceException('No map found to add a marker to.');
}
$item = end($items);
$parameters = $this->getOptions();
$options = array_replace_recursive(
['markers' => $parameters['markers']],
$item->getOptions()['markers'],
$options
);
$item->marker($latitude, $longitude, $options);
return $this;
}
/**
* Add a new map information window.
*
* @param float $latitude
* @param float $longitude
* @param string $content
* @param array $options
*
* @throws MapperException
*
* @return self
*/
public function informationWindow($latitude, $longitude, $content = '', array $options = [])
{
$items = $this->getItems();
if (empty($items)) {
throw new MapperInstanceException('No map found to add a information window to.');
}
$item = end($items);
$parameters = $this->getOptions();
$options = array_replace_recursive(
['markers' => $parameters['markers']],
$item->getOptions()['markers'],
$options,
($content !== '' ? ['markers' => ['content' => $content]] : [])
);
$item->marker($latitude, $longitude, $options);
return $this;
}
/**
* Add a new map polyline.
*
* @param array $coordinates
* @param array $options
*
* @throws MapperException
*
* @return self
*/
public function polyline(array $coordinates = [], array $options = [])
{
$items = $this->getItems();
if (empty($items)) {
throw new MapperInstanceException('No map found to add a polyline to.');
}
$defaults = [
'coordinates' => $coordinates,
'geodesic' => false,
'strokeColor' => '#FF0000',
'strokeOpacity' => 0.8,
'strokeWeight' => 2,
'editable' => false
];
$item = end($items);
$options = array_replace_recursive(
$defaults,
$options
);
$item->shape('polyline', $coordinates, $options);
return $this;
}
/**
* Add a new map polygon.
*
* @param array $coordinates
* @param array $options
*
* @throws MapperException
*
* @return self
*/
public function polygon(array $coordinates = [], array $options = [])
{
$items = $this->getItems();
if (empty($items)) {
throw new MapperInstanceException('No map found to add a polygon to.');
}
$defaults = [
'coordinates' => $coordinates,
'strokeColor' => '#FF0000',
'strokeOpacity' => 0.8,
'strokeWeight' => 2,
'fillColor' => '#FF0000',
'fillOpacity' => 0.35,
'editable' => false
];
$item = end($items);
$options = array_replace_recursive(
$defaults,
$options
);
$item->shape('polygon', $coordinates, $options);
return $this;
}
/**
* Add a new map rectangle.
*
* @param array $coordinates
* @param array $options
*
* @throws MapperException
*
* @return self
*/
public function rectangle(array $coordinates = [], array $options = [])
{
$items = $this->getItems();
if (empty($items)) {
throw new MapperInstanceException('No map found to add a rectangle to.');
}
$defaults = [
'coordinates' => $coordinates,
'strokeColor' => '#FF0000',
'strokeOpacity' => 0.8,
'strokeWeight' => 2,
'fillColor' => '#FF0000',
'fillOpacity' => 0.35,
'editable' => false
];
$item = end($items);
$options = array_replace_recursive(
$defaults,
$options
);
$item->shape('rectangle', $coordinates, $options);
return $this;
}
/**
* Add a new map circle.
*
* @param array $coordinates
* @param array $options
*
* @throws MapperException
*
* @return self
*/
public function circle(array $coordinates = [], array $options = [])
{
$items = $this->getItems();
if (empty($items)) {
throw new MapperInstanceException('No map found to add a circle to.');
}
$defaults = [
'coordinates' => $coordinates,
'strokeColor' => '#FF0000',
'strokeOpacity' => 0.8,
'strokeWeight' => 2,
'fillColor' => '#FF0000',
'fillOpacity' => 0.35,
'radius' => 100000,
'editable' => false
];
$item = end($items);
$options = array_replace_recursive(
$defaults,
$options
);
$item->shape('circle', $coordinates, $options);
return $this;
}
}