* @author Peter Grassberger < petertheone@gmail.com >
*/
class GoogleMapsService implements MappingService {
/**
* Maps user input map types to the Google Maps names for the map types.
*/
private const MAP_TYPES = [
'normal' => 'ROADMAP',
'roadmap' => 'ROADMAP',
'satellite' => 'SATELLITE',
'hybrid' => 'HYBRID',
'terrain' => 'TERRAIN',
'physical' => 'TERRAIN',
'earth' => 'earth'
];
private const TYPE_CONTROL_STYLES = [
'default' => 'DEFAULT',
'horizontal' => 'HORIZONTAL_BAR',
'dropdown' => 'DROPDOWN_MENU'
];
private $addedDependencies = [];
public function getName(): string {
return 'googlemaps3';
}
public function getAliases(): array {
return [ 'googlemaps', 'google' ];
}
public function hasAlias( string $alias ): bool {
return in_array( $alias, [ 'googlemaps', 'google' ] );
}
public function getParameterInfo(): array {
global $egMapsGMaps3Type, $egMapsGMaps3Types, $egMapsGMaps3Controls, $egMapsGMaps3Layers;
global $egMapsGMaps3DefTypeStyle, $egMapsGMaps3DefZoomStyle, $egMapsGMaps3AutoInfoWindows;
global $egMapsResizableByDefault;
$params = MapsFunctions::getCommonParameters();
$params['visitedicon'] = [
'default' => '',
'message' => 'maps-displaymap-par-visitedicon',
];
$params['wmsoverlay'] = [
'type' => 'wmsoverlay',
'default' => false,
'delimiter' => ' ',
'message' => 'maps-displaymap-par-wmsoverlay',
];
$params['zoom'] = [
'type' => 'integer',
'range' => [ 0, 20 ],
'default' => $GLOBALS['egMapsGMaps3Zoom'],
'message' => 'maps-par-zoom',
];
$params['type'] = [
'default' => $egMapsGMaps3Type,
'values' => self::getTypeNames(),
'message' => 'maps-googlemaps3-par-type',
'post-format' => function ( $value ) {
return GoogleMapsService::MAP_TYPES[strtolower( $value )];
},
];
$params['types'] = [
'dependencies' => 'type',
'default' => $egMapsGMaps3Types,
'values' => self::getTypeNames(),
'message' => 'maps-googlemaps3-par-types',
'islist' => true,
'post-format' => function ( array $value ) {
foreach ( $value as &$part ) {
$part = self::MAP_TYPES[strtolower( $part )];
}
return $value;
},
];
$params['layers'] = [
'default' => $egMapsGMaps3Layers,
'values' => [
'traffic',
'bicycling',
'transit'
],
'message' => 'maps-googlemaps3-par-layers',
'islist' => true,
];
$params['controls'] = [
'default' => $egMapsGMaps3Controls,
'values' => [
'pan',
'zoom',
'type',
'scale',
'streetview',
'rotate'
],
'message' => 'maps-googlemaps3-par-controls',
'islist' => true,
'post-format' => function ( $value ) {
return array_map( 'strtolower', $value );
},
];
$params['zoomstyle'] = [
'default' => $egMapsGMaps3DefZoomStyle,
'values' => [ 'default', 'small', 'large' ],
'message' => 'maps-googlemaps3-par-zoomstyle',
'post-format' => 'strtoupper',
];
$params['typestyle'] = [
'default' => $egMapsGMaps3DefTypeStyle,
'values' => array_keys( self::TYPE_CONTROL_STYLES ),
'message' => 'maps-googlemaps3-par-typestyle',
'post-format' => function ( $value ) {
return self::TYPE_CONTROL_STYLES[strtolower( $value )];
},
];
$params['autoinfowindows'] = [
'type' => 'boolean',
'default' => $egMapsGMaps3AutoInfoWindows,
'message' => 'maps-googlemaps3-par-autoinfowindows',
];
$params['resizable'] = [
'type' => 'boolean',
'default' => $egMapsResizableByDefault,
'message' => 'maps-par-resizable',
];
$params['kmlrezoom'] = [
'type' => 'boolean',
'default' => $GLOBALS['egMapsRezoomForKML'],
'message' => 'maps-googlemaps3-par-kmlrezoom',
];
$params['poi'] = [
'type' => 'boolean',
'default' => $GLOBALS['egMapsShowPOI'],
'message' => 'maps-googlemaps3-par-poi',
];
$params['cluster'] = [
'aliases' => [ 'markercluster' ],
'type' => 'boolean',
'default' => false,
'message' => 'maps-par-markercluster',
];
$params['clustergridsize'] = [
'type' => 'integer',
'default' => 60,
'message' => 'maps-googlemaps3-par-clustergridsize',
];
$params['clustermaxzoom'] = [
'type' => 'integer',
'default' => 20,
'message' => 'maps-par-clustermaxzoom',
];
$params['clusterzoomonclick'] = [
'type' => 'boolean',
'default' => true,
'message' => 'maps-par-clusterzoomonclick',
];
$params['clusteraveragecenter'] = [
'type' => 'boolean',
'default' => true,
'message' => 'maps-googlemaps3-par-clusteraveragecenter',
];
$params['clusterminsize'] = [
'type' => 'integer',
'default' => 2,
'message' => 'maps-googlemaps3-par-clusterminsize',
];
$params['imageoverlays'] = [
'type' => 'mapsimageoverlay',
'default' => [],
'delimiter' => ';',
'islist' => true,
'message' => 'maps-googlemaps3-par-imageoverlays',
];
$params['kml'] = [
'default' => [],
'message' => 'maps-par-kml',
'islist' => true,
'post-format' => function( array $kmlFileNames ) {
return array_values(
array_filter(
array_map(
function( string $fileName ) {
return wfExpandUrl( MapsFunctions::getFileUrl( $fileName ) );
},
$kmlFileNames
),
function( string $fileName ) {
return $fileName !== '';
}
)
);
}
];
$params['gkml'] = [
'default' => [],
'message' => 'maps-googlemaps3-par-gkml',
'islist' => true,
];
$params['searchmarkers'] = [
'default' => '',
'message' => 'maps-par-searchmarkers',
// new CriterionSearchMarkers() FIXME
];
$params['fullscreen'] = [
'aliases' => [ 'enablefullscreen' ],
'type' => 'boolean',
'default' => false,
'message' => 'maps-par-enable-fullscreen',
];
$params['scrollwheelzoom'] = [
'aliases' => [ 'scrollzoom' ],
'type' => 'boolean',
'default' => false,
'message' => 'maps-par-scrollwheelzoom',
];
return $params;
}
/**
* Returns the names of all supported map types.
*/
private function getTypeNames(): array {
return array_keys( self::MAP_TYPES );
}
public function newMapId(): string {
static $mapsOnThisPage = 0;
$mapsOnThisPage++;
return 'map_google3_' . $mapsOnThisPage;
}
public function getResourceModules(): array {
return [ 'ext.maps.googlemaps3', 'ext.maps.googlemaps3ajax' ];
}
public static function getApiScript( $langCode, array $urlArgs = [] ) {
$urlArgs = array_merge(
[
'language' => self::getMappedLanguageCode( $langCode )
],
$urlArgs
);
if ( $GLOBALS['egMapsGMaps3ApiKey'] !== '' ) {
$urlArgs['key'] = $GLOBALS['egMapsGMaps3ApiKey'];
}
if ( $GLOBALS['egMapsGMaps3ApiVersion'] !== '' ) {
$urlArgs['v'] = $GLOBALS['egMapsGMaps3ApiVersion'];
}
return Html::linkedScript( '//maps.googleapis.com/maps/api/js?' . wfArrayToCgi( $urlArgs ) );
}
/**
* Maps language codes to Google Maps API v3 compatible values.
*/
private static function getMappedLanguageCode( string $code ): string {
$mappings = [
'en_gb' => 'en-gb',// v3 supports en_gb - but wants us to call it en-gb
'he' => 'iw', // iw is googlish for hebrew
'fj' => 'fil', // google does not support Fijian - use Filipino as close(?) supported relative
];
if ( array_key_exists( $code, $mappings ) ) {
return $mappings[$code];
}
return $code;
}
public function getDependencyHtml( array $params ): string {
$dependencies = [];
// Only add dependencies that have not yet been added.
foreach ( $this->getDependencies() as $dependency ) {
if ( !in_array( $dependency, $this->addedDependencies ) ) {
$dependencies[] = $dependency;
$this->addedDependencies[] = $dependency;
}
}
// If there are dependencies, put them all together in a string, otherwise return false.
return $dependencies !== [] ? implode( '', $dependencies ) : false;
}
private function getDependencies(): array {
return [
self::getApiScript(
is_string( $GLOBALS['egMapsGMaps3Language'] ) ?
$GLOBALS['egMapsGMaps3Language'] : $GLOBALS['egMapsGMaps3Language']->getCode()
)
];
}
public function processingResultToMapParams( ProcessingResult $processingResult ): array {
$parameters = $processingResult->getParameters();
if ( array_key_exists( 'zoom', $parameters ) && $parameters['zoom']->wasSetToDefault() && count(
$parameters['coordinates']->getValue()
) > 1 ) {
$parameters['zoom'] = $this->getParameterWithValue( $parameters['zoom'], false );
}
$mapParams = [];
foreach ( $parameters as $parameter ) {
$mapParams[$parameter->getName()] = $parameter->getValue();
}
return $mapParams;
}
private function getParameterWithValue( ProcessedParam $param, $value ) {
return new ProcessedParam(
$param->getName(),
$value,
$param->wasSetToDefault(),
$param->getOriginalName(),
$param->getOriginalValue()
);
}
}