summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/Maps/src/SemanticMW/ResultPrinters/MapPrinter.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/Maps/src/SemanticMW/ResultPrinters/MapPrinter.php')
-rw-r--r--www/wiki/extensions/Maps/src/SemanticMW/ResultPrinters/MapPrinter.php403
1 files changed, 403 insertions, 0 deletions
diff --git a/www/wiki/extensions/Maps/src/SemanticMW/ResultPrinters/MapPrinter.php b/www/wiki/extensions/Maps/src/SemanticMW/ResultPrinters/MapPrinter.php
new file mode 100644
index 00000000..6ab945f6
--- /dev/null
+++ b/www/wiki/extensions/Maps/src/SemanticMW/ResultPrinters/MapPrinter.php
@@ -0,0 +1,403 @@
+<?php
+
+namespace Maps\SemanticMW\ResultPrinters;
+
+use FormatJson;
+use Html;
+use Linker;
+use Maps\Elements\BaseElement;
+use Maps\Elements\Location;
+use Maps\FileUrlFinder;
+use Maps\MappingService;
+use Maps\MapsFunctions;
+use Maps\Presentation\ElementJsonSerializer;
+use Maps\Presentation\MapHtmlBuilder;
+use Maps\Presentation\WikitextParser;
+use Maps\Presentation\WikitextParsers\LocationParser;
+use ParamProcessor\ParamDefinition;
+use Parser;
+use SMW\Query\ResultPrinters\ResultPrinter;
+use SMWOutputs;
+use SMWQueryResult;
+use Title;
+
+/**
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ * @author Peter Grassberger < petertheone@gmail.com >
+ */
+class MapPrinter extends ResultPrinter {
+
+ private static $services = [];
+
+ /**
+ * @var LocationParser
+ */
+ private $locationParser;
+
+ /**
+ * @var FileUrlFinder
+ */
+ private $fileUrlFinder;
+
+ /**
+ * @var MappingService
+ */
+ private $service;
+
+ /**
+ * @var WikitextParser
+ */
+ private $wikitextParser;
+
+ /**
+ * @var ElementJsonSerializer
+ */
+ private $elementSerializer;
+
+ /**
+ * @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 );
+ }
+
+ /**
+ * @since 3.4
+ * FIXME: this is a temporary hack that should be replaced when SMW allows for dependency
+ * injection in query printers.
+ *
+ * @param MappingService $service
+ */
+ public static function registerService( MappingService $service ) {
+ self::$services[$service->getName()] = $service;
+ }
+
+ public static function registerDefaultService( $serviceName ) {
+ self::$services['map'] = self::$services[$serviceName];
+ }
+
+ private function getParser(): Parser {
+ $parser = $GLOBALS['wgParser'];
+
+ if ( $parser instanceof \StubObject ) {
+ return $parser->_newObject();
+ }
+
+ return $parser;
+ }
+
+ private function getParserClone(): Parser {
+ $parser = $this->getParser();
+ return clone $parser;
+ }
+
+ /**
+ * Builds up and returns the HTML for the map, with the queried coordinate data on it.
+ *
+ * @param SMWQueryResult $res
+ * @param int $outputMode
+ *
+ * @return string
+ */
+ public final function getResultText( SMWQueryResult $res, $outputMode ) {
+ if ( $this->fatalErrorMsg !== false ) {
+ return $this->fatalErrorMsg;
+ }
+
+ $factory = \Maps\MapsFactory::newDefault();
+ $this->locationParser = $factory->newLocationParser();
+ $this->fileUrlFinder = $factory->getFileUrlFinder();
+
+ $this->wikitextParser = new WikitextParser( $this->getParserClone() );
+ $this->elementSerializer = new ElementJsonSerializer( $this->wikitextParser );
+
+ $this->addTrackingCategoryIfNeeded();
+
+ $params = $this->params;
+
+ $queryHandler = new QueryHandler( $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 );
+
+ $params['lines'] = $this->elementsToJson( $params['lines'] );
+ $params['polygons'] = $this->elementsToJson( $params['polygons'] );
+ $params['circles'] = $this->elementsToJson( $params['circles'] );
+ $params['rectangles'] = $this->elementsToJson( $params['rectangles'] );
+
+ $params['ajaxquery'] = urlencode( $params['ajaxquery'] );
+
+ if ( $params['locations'] === [] ) {
+ return $params['default'];
+ }
+
+ // 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() && count( $params['locations'] ) > 1 ) {
+ $params['zoom'] = false;
+ }
+
+ $mapId = $this->service->newMapId();
+
+ SMWOutputs::requireHeadItem(
+ $mapId,
+ $this->service->getDependencyHtml( $params )
+ );
+
+ foreach ( $this->service->getResourceModules() as $resourceModule ) {
+ SMWOutputs::requireResource( $resourceModule );
+ }
+
+ if ( array_key_exists( 'source', $params ) ) {
+ unset( $params['source'] );
+ }
+
+ return ( new MapHtmlBuilder() )->getMapHTML(
+ $params,
+ $mapId,
+ $this->service->getName()
+ );
+ }
+
+ private function elementsToJson( array $elements ) {
+ return array_map(
+ function( BaseElement $element ) {
+ return $this->elementSerializer->elementToJson( $element );
+ },
+ $elements
+ );
+ }
+
+ private function addTrackingCategoryIfNeeded() {
+ /**
+ * @var Parser $wgParser
+ */
+ global $wgParser;
+
+ if ( $GLOBALS['egMapsEnableCategory'] && $wgParser->getOutput() !== null ) {
+ $wgParser->addTrackingCategory( 'maps-tracking-category' );
+ }
+ }
+
+ /**
+ * 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 QueryHandler $queryHandler
+ */
+ private function handleMarkerData( array &$params, QueryHandler $queryHandler ) {
+ $params['centre'] = $this->getCenter( $params['centre'] );
+
+ $iconUrl = $this->fileUrlFinder->getUrlForFileName( $params['icon'] );
+ $visitedIconUrl = $this->fileUrlFinder->getUrlForFileName( $params['visitedicon'] );
+
+ $params['locations'] = $this->getJsonForStaticLocations(
+ $params['staticlocations'],
+ $params,
+ $iconUrl,
+ $visitedIconUrl
+ );
+
+ unset( $params['staticlocations'] );
+
+ $params['locations'] = array_merge(
+ $params['locations'],
+ $this->getJsonForLocations(
+ $queryHandler->getLocations(),
+ $params,
+ $iconUrl,
+ $visitedIconUrl
+ )
+ );
+ }
+
+ private function getCenter( $coordinatesOrAddress ) {
+ if ( $coordinatesOrAddress === false ) {
+ return false;
+ }
+
+ try {
+ // FIXME: a Location makes no sense here, since the non-coordinate data is not used
+ $location = $this->locationParser->parse( $coordinatesOrAddress );
+ }
+ catch ( \Exception $ex ) {
+ // TODO: somehow report this to the user
+ return false;
+ }
+
+ return $location->getJSONObject();
+ }
+
+ private function getJsonForStaticLocations( array $staticLocations, array $params, $iconUrl, $visitedIconUrl ) {
+ $locationsJson = [];
+
+ foreach ( $staticLocations as $location ) {
+ $locationsJson[] = $this->getJsonForStaticLocation(
+ $location,
+ $params,
+ $iconUrl,
+ $visitedIconUrl
+ );
+ }
+
+ return $locationsJson;
+ }
+
+ private function getJsonForStaticLocation( Location $location, array $params, $iconUrl, $visitedIconUrl ) {
+ $jsonObj = $location->getJSONObject( $params['title'], $params['label'], $iconUrl, '', '', $visitedIconUrl );
+
+ $this->elementSerializer->titleAndText( $jsonObj );
+
+ if ( $params['pagelabel'] ) {
+ $jsonObj['inlineLabel'] = Linker::link( Title::newFromText( $jsonObj['title'] ) );
+ }
+
+ return $jsonObj;
+ }
+
+ /**
+ * @param Location[] $locations
+ * @param array $params
+ * @param string $iconUrl
+ * @param string $visitedIconUrl
+ *
+ * @return array
+ */
+ private function getJsonForLocations( iterable $locations, array $params, string $iconUrl, string $visitedIconUrl ): array {
+ $locationsJson = [];
+
+ foreach ( $locations as $location ) {
+ $jsonObj = $location->getJSONObject(
+ $params['title'],
+ $params['label'],
+ $iconUrl,
+ '',
+ '',
+ $visitedIconUrl
+ );
+
+ $jsonObj['title'] = strip_tags( $jsonObj['title'] );
+
+ $locationsJson[] = $jsonObj;
+ }
+
+ return $locationsJson;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Returns an array containing the parameter info.
+ *
+ * @return array
+ */
+ private function getParameterInfo() {
+ global $smgQPShowTitle, $smgQPTemplate, $smgQPHideNamespace;
+
+ $params = array_merge(
+ ParamDefinition::getCleanDefinitions( MapsFunctions::getCommonParameters() ),
+ $this->service->getParameterInfo()
+ );
+
+ $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'] = [
+ 'default' => '',
+ ];
+
+ $params['ajaxquery'] = [
+ '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;
+ }
+ }
+
+ return $params;
+ }
+}