summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/Maps/src/SemanticMW/DataValues/CoordinateValue.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/Maps/src/SemanticMW/DataValues/CoordinateValue.php')
-rw-r--r--www/wiki/extensions/Maps/src/SemanticMW/DataValues/CoordinateValue.php266
1 files changed, 266 insertions, 0 deletions
diff --git a/www/wiki/extensions/Maps/src/SemanticMW/DataValues/CoordinateValue.php b/www/wiki/extensions/Maps/src/SemanticMW/DataValues/CoordinateValue.php
new file mode 100644
index 00000000..47de2632
--- /dev/null
+++ b/www/wiki/extensions/Maps/src/SemanticMW/DataValues/CoordinateValue.php
@@ -0,0 +1,266 @@
+<?php
+
+namespace Maps\SemanticMW\DataValues;
+
+use DataValues\Geo\Parsers\LatLongParser;
+use DataValues\Geo\Values\LatLongValue;
+use InvalidArgumentException;
+use Maps\MapsFactory;
+use Maps\Presentation\MapsDistanceParser;
+use SMW\Query\Language\Description;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\QueryComparator;
+use SMWDataItem;
+use SMWDataValue;
+use SMWDIGeoCoord;
+use SMWOutputs;
+use ValueParsers\ParseException;
+
+/**
+ * @property SMWDIGeoCoord m_dataitem
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ * @author Markus Krötzsch
+ */
+class CoordinateValue extends SMWDataValue {
+
+ private $wikiValue;
+
+ /**
+ * Overwrite SMWDataValue::getQueryDescription() to be able to process
+ * comparators between all values.
+ *
+ * @param string $value
+ *
+ * @return Description
+ * @throws InvalidArgumentException
+ */
+ public function getQueryDescription( $value ) {
+ if ( !is_string( $value ) ) {
+ throw new InvalidArgumentException( '$value needs to be a string' );
+ }
+
+ list( $distance, $comparator ) = $this->parseUserValue( $value );
+ $distance = $this->parserDistance( $distance );
+
+ $this->setUserValue( $value );
+
+ switch ( true ) {
+ case !$this->isValid():
+ return new ThingDescription();
+ case $distance !== false:
+ return new \Maps\SemanticMW\ValueDescriptions\AreaDescription(
+ $this->getDataItem(),
+ $comparator,
+ $distance
+ );
+ default:
+ return new \Maps\SemanticMW\ValueDescriptions\CoordinateDescription(
+ $this->getDataItem(),
+ null,
+ $comparator
+ );
+ }
+ }
+
+ /**
+ * @see SMWDataValue::parseUserValue
+ */
+ protected function parseUserValue( $value ) {
+ if ( !is_string( $value ) ) {
+ throw new InvalidArgumentException( '$value needs to be a string' );
+ }
+
+ $this->wikiValue = $value;
+
+ $comparator = SMW_CMP_EQ;
+ $distance = false;
+
+ if ( $value === '' ) {
+ $this->addError( wfMessage( 'smw_novalues' )->text() );
+ } else {
+ $comparator = QueryComparator::getInstance()->extractComparatorFromString( $value );
+
+ list( $coordinates, $distance ) = $this->findValueParts( $value );
+
+ $this->tryParseAndSetDataItem( $coordinates );
+ }
+
+ return [ $distance, $comparator ];
+ }
+
+ private function findValueParts( string $value ): array {
+ $parts = explode( '(', $value );
+
+ $coordinates = trim( array_shift( $parts ) );
+ $distance = count( $parts ) > 0 ? trim( array_shift( $parts ) ) : false;
+
+ return [ $coordinates, $distance ];
+ }
+
+ private function tryParseAndSetDataItem( string $coordinates ) {
+ $parser = new LatLongParser();
+
+ try {
+ $value = $parser->parse( $coordinates );
+ $this->m_dataitem = new SMWDIGeoCoord( $value->getLatitude(), $value->getLongitude() );
+ }
+ catch ( ParseException $parseException ) {
+ $this->addError( wfMessage( 'maps_unrecognized_coords', $coordinates, 1 )->text() );
+
+ // Make sure this is always set
+ // TODO: Why is this needed?!
+ $this->m_dataitem = new SMWDIGeoCoord( [ 'lat' => 0, 'lon' => 0 ] );
+ }
+ }
+
+ private function parserDistance( $distance ) {
+ if ( $distance !== false ) {
+ $distance = substr( trim( $distance ), 0, -1 );
+
+ if ( !MapsDistanceParser::isDistance( $distance ) ) {
+ $this->addError( wfMessage( 'semanticmaps-unrecognizeddistance', $distance )->text() );
+ $distance = false;
+ }
+ }
+
+ return $distance;
+ }
+
+ /**
+ * @see SMWDataValue::getShortHTMLText
+ *
+ * @since 0.6
+ */
+ public function getShortHTMLText( $linker = null ) {
+ return $this->getShortWikiText( $linker );
+ }
+
+ /**
+ * @see SMWDataValue::getShortWikiText
+ */
+ public function getShortWikiText( $linked = null ) {
+ if ( $this->isValid() ) {
+ if ( $this->m_caption === false ) {
+ return $this->getFormattedCoord( $this->m_dataitem );
+ }
+
+ return $this->m_caption;
+ }
+
+ return $this->getErrorText();
+ }
+
+ /**
+ * @param SMWDIGeoCoord $dataItem
+ * @param string|null $format
+ *
+ * @return string|null
+ */
+ private function getFormattedCoord( SMWDIGeoCoord $dataItem, string $format = null ) {
+ return MapsFactory::globalInstance()->getCoordinateFormatter()->format(
+ new LatLongValue(
+ $dataItem->getLatitude(),
+ $dataItem->getLongitude()
+ ),
+ $format ?? $GLOBALS['smgQPCoodFormat'],
+ $GLOBALS['smgQPCoodDirectional']
+ );
+ }
+
+ /**
+ * @see SMWDataValue::getLongHTMLText
+ */
+ public function getLongHTMLText( $linker = null ) {
+ return $this->getLongWikiText( $linker );
+ }
+
+ /**
+ * @see SMWDataValue::getLongWikiText
+ *
+ * @since 0.6
+ */
+ public function getLongWikiText( $linked = null ) {
+ if ( $this->isValid() ) {
+ SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
+
+ // TODO: fix lang keys so they include the space and coordinates.
+ $coordinateSet = $this->m_dataitem->getCoordinateSet();
+
+ $text = $this->getFormattedCoord( $this->m_dataitem );
+
+ $lines = [
+ wfMessage( 'semanticmaps-latitude', $coordinateSet['lat'] )->inContentLanguage()->escaped(),
+ wfMessage( 'semanticmaps-longitude', $coordinateSet['lon'] )->inContentLanguage()->escaped(),
+ ];
+
+ if ( array_key_exists( 'alt', $coordinateSet ) ) {
+ $lines[] = wfMessage( 'semanticmaps-altitude', $coordinateSet['alt'] )->inContentLanguage()->escaped();
+ }
+
+ return '<span class="smwttinline">' . htmlspecialchars( $text ) . '<span class="smwttcontent">' .
+ implode( '<br />', $lines ) .
+ '</span></span>';
+ } else {
+ return $this->getErrorText();
+ }
+ }
+
+ /**
+ * @see SMWDataValue::getWikiValue
+ */
+ public function getWikiValue() {
+ return $this->wikiValue;
+ }
+
+ /**
+ * @see SMWDataValue::setDataItem
+ *
+ * @param SMWDataItem $dataItem
+ *
+ * @return boolean
+ */
+ protected function loadDataItem( SMWDataItem $dataItem ) {
+ if ( $dataItem instanceof SMWDIGeoCoord ) {
+ $formattedValue = $this->getFormattedCoord( $dataItem );
+
+ if ( $formattedValue !== null ) {
+ $this->wikiValue = $formattedValue;
+ $this->m_dataitem = $dataItem;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Create links to mapping services based on a wiki-editable message. The parameters
+ * available to the message are:
+ *
+ * $1: The location in non-directional float notation.
+ * $2: The location in directional DMS notation.
+ * $3: The latitude in non-directional float notation.
+ * $4 The longitude in non-directional float notation.
+ *
+ * @return array
+ */
+ protected function getServiceLinkParams() {
+ $coordinateSet = $this->m_dataitem->getCoordinateSet();
+ return [
+ $this->getFormattedCoord( $this->m_dataitem, 'float' ), // TODO
+ $this->getFormattedCoord( $this->m_dataitem, 'dms' ), // TODO
+ $coordinateSet['lat'],
+ $coordinateSet['lon']
+ ];
+ }
+
+ /**
+ * @return SMWDIGeoCoord|\SMWDIError
+ */
+ public function getDataItem() {
+ return parent::getDataItem();
+ }
+
+}