| Current File : /home/jvzmxxx/wiki1/extensions/Maps/SemanticMaps/src/queryprinters/SM_MapPrinter.php |
<?php
use Maps\Elements\Location;
use Maps\Element;
use Maps\Elements\BaseElement;
use ParamProcessor\ParamDefinition;
/**
* Query printer for maps. Is invoked via SMMapper.
* Can be overridden per service to have custom output.
*
* @ingroup SemanticMaps
*
* @licence GNU GPL v2+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
* @author Peter Grassberger < petertheone@gmail.com >
*/
class SMMapPrinter extends SMW\ResultPrinter {
private static $services = [];
/**
* @since 3.4
* FIXME: this is a temporary hack that should be replaced when SMW allows for dependency
* injection in query printers.
*
* @param MapsMappingService $service
*/
public static function registerService( MapsMappingService $service ) {
self::$services[$service->getName()] = $service;
}
public static function registerDefaultService( $serviceName ) {
self::$services['map'] = self::$services[$serviceName];
}
/**
* @var MapsMappingService
*/
private $service;
/**
* @var string|boolean
*/
private $fatalErrorMsg = false;
/**
* @param string $format
* @param bool $inline
*/
public function __construct( $format, $inline = true ) {
$this->service = self::$services[$format];
parent::__construct( $format, $inline );
}
/**
* Returns an array containing the parameter info.
*
* @return array
*/
private function getParameterInfo() {
global $smgQPShowTitle, $smgQPTemplate, $smgQPHideNamespace;
$params = ParamDefinition::getCleanDefinitions( MapsMapper::getCommonParameters() );
$this->service->addParameterInfo( $params );
$params['staticlocations'] = [
'type' => 'mapslocation',
'aliases' => [ 'locations', 'points' ],
'default' => [],
'islist' => true,
'delimiter' => ';',
'message' => 'semanticmaps-par-staticlocations',
];
$params['showtitle'] = [
'type' => 'boolean',
'aliases' => 'show title',
'default' => $smgQPShowTitle,
];
$params['hidenamespace'] = [
'type' => 'boolean',
'aliases' => 'hide namespace',
'default' => $smgQPHideNamespace,
];
$params['template'] = [
'default' => $smgQPTemplate,
];
$params['userparam'] = [
'default' => '',
];
$params['activeicon'] = [
'type' => 'string',
'default' => '',
];
$params['pagelabel'] = [
'type' => 'boolean',
'default' => false,
];
$params['ajaxcoordproperty'] = array(
'default' => '',
);
$params['ajaxquery'] = array(
'default' => '',
'type' => 'string'
);
// Messages:
// semanticmaps-par-staticlocations, semanticmaps-par-showtitle, semanticmaps-par-hidenamespace,
// semanticmaps-par-template, semanticmaps-par-userparam, semanticmaps-par-activeicon,
// semanticmaps-par-pagelabel, semanticmaps-par-ajaxcoordproperty semanticmaps-par-ajaxquery
foreach ( $params as $name => &$data ) {
if ( is_array( $data ) && !array_key_exists( 'message', $data ) ) {
$data['message'] = 'semanticmaps-par-' . $name;
}
}
$params = array_merge( $params, MapsDisplayMap::getCommonMapParams() );
return $params;
}
/**
* Builds up and returns the HTML for the map, with the queried coordinate data on it.
*
* @param SMWQueryResult $res
* @param $outputmode
*
* @return array or string
*/
public final function getResultText( SMWQueryResult $res, $outputmode ) {
if ( $this->fatalErrorMsg !== false ) {
return $this->fatalErrorMsg;
}
/**
* @var Parser $wgParser
*/
global $wgParser;
if ( $GLOBALS['egMapsEnableCategory'] && $wgParser->getOutput() !== null ) {
$wgParser->addTrackingCategory( 'maps-tracking-category' );
}
$params = $this->params;
$queryHandler = new SMQueryHandler( $res, $outputmode );
$queryHandler->setLinkStyle($params['link']);
$queryHandler->setHeaderStyle($params['headers']);
$queryHandler->setShowSubject( $params['showtitle'] );
$queryHandler->setTemplate( $params['template'] );
$queryHandler->setUserParam( $params['userparam'] );
$queryHandler->setHideNamespace( $params['hidenamespace'] );
$queryHandler->setActiveIcon( $params['activeicon'] );
$this->handleMarkerData( $params, $queryHandler );
$locationAmount = count( $params['locations'] );
$params['ajaxquery'] = urlencode( $params['ajaxquery'] );
if ( $locationAmount > 0 ) {
// We can only take care of the zoom defaulting here,
// as not all locations are available in whats passed to Validator.
if ( $this->fullParams['zoom']->wasSetToDefault() && $locationAmount > 1 ) {
$params['zoom'] = false;
}
$mapName = $this->service->getMapId();
SMWOutputs::requireHeadItem(
$mapName,
$this->service->getDependencyHtml() .
$configVars = Skin::makeVariablesScript( $this->service->getConfigVariables() )
);
foreach ( $this->service->getResourceModules() as $resourceModule ) {
SMWOutputs::requireResource( $resourceModule );
}
if ( array_key_exists( 'source', $params ) ) {
unset( $params['source'] );
}
return $this->getMapHTML( $params, $wgParser, $mapName );
}
else {
return $params['default'];
}
}
/**
* Returns the HTML to display the map.
*
* @param array $params
* @param Parser $parser
* @param string $mapName
*
* @return string
*/
private function getMapHTML( array $params, Parser $parser, $mapName ) {
return Html::rawElement(
'div',
[
'id' => $mapName,
'style' => "width: {$params['width']}; height: {$params['height']}; background-color: #cccccc; overflow: hidden;",
'class' => 'maps-map maps-' . $this->service->getName()
],
wfMessage( 'maps-loading-map' )->inContentLanguage()->escaped() .
Html::element(
'div',
[ 'style' => 'display:none', 'class' => 'mapdata' ],
FormatJson::encode( $this->getJSONObject( $params, $parser ) )
)
);
}
/**
* Returns a PHP object to encode to JSON with the map data.
*
* @param array $params
* @param Parser $parser
*
* @return mixed
*/
private function getJSONObject( array $params, Parser $parser ) {
return $params;
}
/**
* Converts the data in the coordinates parameter to JSON-ready objects.
* These get stored in the locations parameter, and the coordinates on gets deleted.
*
* @param array &$params
* @param SMQueryHandler $queryHandler
*/
private function handleMarkerData( array &$params, SMQueryHandler $queryHandler ) {
if ( is_object( $params['centre'] ) ) {
$params['centre'] = $params['centre']->getJSONObject();
}
$iconUrl = MapsMapper::getFileUrl( $params['icon'] );
$visitedIconUrl = MapsMapper::getFileUrl( $params['visitedicon'] );
$params['locations'] = $this->getJsonForStaticLocations(
$params['staticlocations'],
$params,
$iconUrl,
$visitedIconUrl
);
unset( $params['staticlocations'] );
$this->addShapeData( $queryHandler->getShapes(), $params, $iconUrl, $visitedIconUrl );
if ( $params['format'] === 'openlayers' ) {
$params['layers'] = MapsDisplayMapRenderer::evilOpenLayersHack( $params['layers'] );
}
}
private function getJsonForStaticLocations( array $staticLocations, array $params, $iconUrl, $visitedIconUrl ) {
/**
* @var Parser $wgParser
*/
global $wgParser;
$parser = version_compare( $GLOBALS['wgVersion'], '1.18', '<' ) ? $wgParser : clone $wgParser;
$locationsJson = [];
foreach ( $staticLocations as $location ) {
$locationsJson[] = $this->getJsonForStaticLocation(
$location,
$params,
$iconUrl,
$visitedIconUrl,
$parser
);
}
return $locationsJson;
}
private function getJsonForStaticLocation( Location $location, array $params, $iconUrl, $visitedIconUrl, Parser $parser ) {
$jsonObj = $location->getJSONObject( $params['title'], $params['label'], $iconUrl, '', '', $visitedIconUrl );
$jsonObj['title'] = $parser->parse( $jsonObj['title'], $parser->getTitle(), new ParserOptions() )->getText();
$jsonObj['text'] = $parser->parse( $jsonObj['text'], $parser->getTitle(), new ParserOptions() )->getText();
$hasTitleAndtext = $jsonObj['title'] !== '' && $jsonObj['text'] !== '';
$jsonObj['text'] = ( $hasTitleAndtext ? '<b>' . $jsonObj['title'] . '</b><hr />' : $jsonObj['title'] ) . $jsonObj['text'];
$jsonObj['title'] = strip_tags( $jsonObj['title'] );
if ( $params['pagelabel'] ) {
$jsonObj['inlineLabel'] = Linker::link( Title::newFromText( $jsonObj['title'] ) );
}
return $jsonObj;
}
/**
* @param Element[] $queryShapes
* @param array $params
* @param string $iconUrl
* @param string $visitedIconUrl
*/
private function addShapeData( array $queryShapes, array &$params, $iconUrl, $visitedIconUrl ) {
$params['locations'] = array_merge(
$params['locations'],
$this->getJsonForLocations(
$queryShapes['locations'],
$params,
$iconUrl,
$visitedIconUrl
)
);
$params['lines'] = $this->getElementJsonArray( $queryShapes['lines'], $params );
$params['polygons'] = $this->getElementJsonArray( $queryShapes['polygons'], $params );
}
/**
* @param Location[] $locations
* @param array $params
* @param string $iconUrl
* @param string $visitedIconUrl
*
* @return array
*/
private function getJsonForLocations( array $locations, array $params, $iconUrl, $visitedIconUrl ) {
$locationsJson = [];
foreach ( $locations as $location ) {
$jsonObj = $location->getJSONObject( $params['title'], $params['label'], $iconUrl, '', '', $visitedIconUrl );
$jsonObj['title'] = strip_tags( $jsonObj['title'] );
$locationsJson[] = $jsonObj;
}
return $locationsJson;
}
/**
* @param BaseElement[] $elements
* @param array $params
*
* @return array
*/
private function getElementJsonArray( array $elements, array $params ) {
$elementsJson = [];
foreach ( $elements as $element ) {
$jsonObj = $element->getJSONObject( $params['title'], $params['label'] );
$elementsJson[] = $jsonObj;
}
return $elementsJson;
}
/**
* Returns the internationalized name of the mapping service.
*
* @return string
*/
public final function getName() {
return wfMessage( 'maps_' . $this->service->getName() )->text();
}
/**
* Returns a list of parameter information, for usage by Special:Ask and others.
*
* @return array
*/
public function getParameters() {
$params = parent::getParameters();
$paramInfo = $this->getParameterInfo();
// Do not display this as an option, as the format already determines it
// TODO: this can probably be done cleaner with some changes in Maps
unset( $paramInfo['mappingservice'] );
$params = array_merge( $params, $paramInfo );
return $params;
}
}