diff options
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/src/DataValues/ValueFormatters/PropertyValueFormatter.php')
-rw-r--r-- | www/wiki/extensions/SemanticMediaWiki/src/DataValues/ValueFormatters/PropertyValueFormatter.php | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/src/DataValues/ValueFormatters/PropertyValueFormatter.php b/www/wiki/extensions/SemanticMediaWiki/src/DataValues/ValueFormatters/PropertyValueFormatter.php new file mode 100644 index 00000000..81407fb6 --- /dev/null +++ b/www/wiki/extensions/SemanticMediaWiki/src/DataValues/ValueFormatters/PropertyValueFormatter.php @@ -0,0 +1,337 @@ +<?php + +namespace SMW\DataValues\ValueFormatters; + +use RuntimeException; +use SMW\ApplicationFactory; +use SMW\Highlighter; +use SMW\Localizer; +use SMW\Message; +use SMWDataValue as DataValue; +use SMW\DataValues\PropertyValue; +use SMW\PropertySpecificationLookup; + +/** + * @license GNU GPL v2+ + * @since 2.5 + * + * @author mwjames + */ +class PropertyValueFormatter extends DataValueFormatter { + + /** + * @var PropertySpecificationLookup + */ + private $propertySpecificationLookup; + + /** + * @since 3.0 + * + * @param PropertySpecificationLookup $propertySpecificationLookup + */ + public function __construct( PropertySpecificationLookup $propertySpecificationLookup ) { + $this->propertySpecificationLookup = $propertySpecificationLookup; + } + + /** + * @since 2.5 + * + * {@inheritDoc} + */ + public function isFormatterFor( DataValue $dataValue ) { + return $dataValue instanceof PropertyValue; + } + + /** + * @since 2.5 + * + * {@inheritDoc} + */ + public function format( $dataValue, $options = null ) { + + if ( !is_array( $options ) ) { + throw new RuntimeException( "Option is not an array!" ); + } + + if ( !$dataValue instanceof PropertyValue ) { + throw new RuntimeException( "The formatter is missing a valid PropertyValue object" ); + } + + $this->dataValue = $dataValue; + + $type = $options[0]; + $linker = isset( $options[1] ) ? $options[1] : null; + + if ( !$this->dataValue->isVisible() ) { + return ''; + } + + if ( $type === self::VALUE ) { + return $this->getWikiValue(); + } + + if ( $type === PropertyValue::FORMAT_LABEL ) { + return $this->getFormattedLabel( $linker ); + } + + if ( $type === PropertyValue::SEARCH_LABEL ) { + return $this->getSearchLabel(); + } + + $wikiPageValue = $this->prepareWikiPageValue( $linker ); + $text = ''; + + if ( $wikiPageValue === null ) { + return ''; + } + + if ( $type === self::WIKI_SHORT ) { + $text = $this->doHighlightText( + $wikiPageValue->getShortWikiText( $linker ), + $this->dataValue->getOption( PropertyValue::OPT_HIGHLIGHT_LINKER ) ? $linker : null + ); + } + + if ( $type === self::HTML_SHORT ) { + $text = $this->doHighlightText( $wikiPageValue->getShortHTMLText( $linker ), $linker ); + } + + if ( $type === self::WIKI_LONG ) { + $text = $this->doHighlightText( $wikiPageValue->getLongWikiText( $linker ) ); + } + + if ( $type === self::HTML_LONG ) { + $text = $this->doHighlightText( $wikiPageValue->getLongHTMLText( $linker ), $linker ); + } + + return $text . $this->hintPreferredLabelUse(); + } + + /** + * Formatting rule set: + * - preferred goes before translation + * - displayTitle goes before translation + * - translation goes before "normal" label + */ + private function getFormattedLabel( $linker = null ) { + + $property = $this->dataValue->getDataItem(); + $output = ''; + $displayTitle = ''; + + $preferredLabel = $property->getPreferredLabel( + $this->dataValue->getOption( PropertyValue::OPT_USER_LANGUAGE ) + ); + + $label = $preferredLabel; + + if ( $preferredLabel === '' && ( $label = $this->findTranslatedPropertyLabel( $property ) ) === '' ) { + $label = $property->getLabel(); + } + + if ( $this->dataValue->getWikiPageValue() !== null ) { + $displayTitle = $this->dataValue->getWikiPageValue()->getDisplayTitle(); + } + + $canonicalLabel = $property->getCanonicalLabel(); + + // Display title goes before a translated label (but not preferred) + if ( $preferredLabel === '' && $displayTitle !== '' ) { + $label = $displayTitle; + // $canonicalLabel = $displayTitle; + } + + // Internal format only used by PropertyValue + $format = $this->dataValue->getOption( PropertyValue::FORMAT_LABEL ); + $this->dataValue->setCaption( $label ); + + if ( $format === self::VALUE ) { + $output = $this->dataValue->getWikiValue(); + } + + if ( $format === self::WIKI_LONG && $linker !== null ) { + $output = $this->dataValue->getLongWikiText( $linker ); + } elseif ( $format === self::WIKI_LONG && $preferredLabel === '' && $displayTitle !== '' ) { + $output = $displayTitle; + } elseif ( $format === self::WIKI_LONG ) { + // Avoid Title::getPrefixedText as it transforms the text to have a + // leading capital letter in some configurations + $output = Localizer::getInstance()->createTextWithNamespacePrefix( SMW_NS_PROPERTY, $label ); + } + + if ( $format === self::HTML_SHORT && $linker !== null ) { + $output = $this->dataValue->getShortHTMLText( $linker ); + } + + // Output both according to the formatting rule set forth by + if ( $canonicalLabel !== $label ) { + $canonicalLabel = \Html::rawElement( + 'span', [ 'style' => 'font-size:small;' ], '(' . $canonicalLabel . ')' ); + $output = $output . ' '. $canonicalLabel; + } + + return $output; + } + + private function getWikiValue() { + + $property = $this->dataValue->getDataItem(); + $languageCode = $this->dataValue->getOption( PropertyValue::OPT_USER_LANGUAGE ); + + if ( ( $preferredLabel = $property->getPreferredLabel( $languageCode ) ) !== '' ) { + return $preferredLabel; + } + + if ( $this->dataValue->getWikiPageValue() !== null && $this->dataValue->getWikiPageValue()->getDisplayTitle() !== '' ) { + return $this->dataValue->getWikiPageValue()->getDisplayTitle(); + } + + if ( ( $translatedPropertyLabel = $this->findTranslatedPropertyLabel( $property ) ) !== '' ) { + return $translatedPropertyLabel; + } + + return $this->dataValue->getDataItem()->getLabel(); + } + + /** + * The display title modifies the search/sort characteristics (#1534), + * (foo:Bar vs. Foo:Bar vs. FOO:bar) therefore select a possible DisplayTitle + * before any other label preference. + */ + private function getSearchLabel() { + + $wikiPageValue = $this->dataValue->getWikiPageValue(); + + if ( $wikiPageValue !== null && ( $displayTitle = $wikiPageValue->getDisplayTitle() ) !== '' ) { + return $displayTitle; + } + + return $this->dataValue->getDataItem()->getLabel(); + } + + private function prepareWikiPageValue( $linker = null ) { + + $wikiPageValue = $this->dataValue->getWikiPageValue(); + + if ( $wikiPageValue === null ) { + return null; + } + + $property = $this->dataValue->getDataItem(); + $caption = $this->dataValue->getCaption(); + + if ( $caption !== false && $caption !== '' ) { + $wikiPageValue->setCaption( $caption ); + } elseif ( ( $preferredLabel = $this->dataValue->getPreferredLabel() ) !== '' ) { + $wikiPageValue->setCaption( $preferredLabel ); + } elseif ( ( $translatedPropertyLabel = $this->findTranslatedPropertyLabel( $property ) ) !== '' ) { + $wikiPageValue->setCaption( $translatedPropertyLabel ); + } else { + $wikiPageValue->setCaption( $property->getLabel() ); + } + + return $wikiPageValue; + } + + private function doHighlightText( $text, $linker = null ) { + + $content = ''; + + if ( !$this->canHighlight( $content, $linker ) ) { + return $text; + } + + $highlighter = Highlighter::factory( + Highlighter::TYPE_PROPERTY, + $this->dataValue->getOption( PropertyValue::OPT_USER_LANGUAGE ) + ); + + $highlighter->setContent( + [ + 'userDefined' => $this->dataValue->getDataItem()->isUserDefined(), + 'caption' => $text, + 'content' => $content !== '' ? $content : Message::get( 'smw_isspecprop' ) + ] + ); + + return $highlighter->getHtml(); + } + + private function canHighlight( &$propertyDescription, $linker ) { + + if ( $this->dataValue->getOption( PropertyValue::OPT_NO_HIGHLIGHT ) === true ) { + return false; + } + + $dataItem = $this->dataValue->getDataItem(); + + $propertyDescription = $this->propertySpecificationLookup->getPropertyDescriptionByLanguageCode( + $dataItem, + $this->dataValue->getOption( PropertyValue::OPT_USER_LANGUAGE ), + $linker + ); + + return !$dataItem->isUserDefined() || $propertyDescription !== ''; + } + + private function hintPreferredLabelUse() { + + if ( !$this->dataValue->isEnabledFeature( SMW_DV_PROV_LHNT ) || + $this->dataValue->getOption( PropertyValue::OPT_NO_PREF_LHNT ) ) { + return ''; + } + + $property = $this->dataValue->getDataItem(); + + $preferredLabel = $property->getPreferredLabel( + $this->dataValue->getOption( PropertyValue::OPT_USER_LANGUAGE ) + ); + + // When comparing with a caption set from the "outside", normalize + // the string to avoid a false negative in case of a non-breaking space + $caption = str_replace( + [ " ", " ", html_entity_decode( ' ', ENT_NOQUOTES, 'UTF-8' ) ], + " ", + $this->dataValue->getCaption() + ); + + if ( $preferredLabel === '' || $caption !== $preferredLabel ) { + return ''; + } + + $label = $property->getLabel(); + + if ( $preferredLabel === $label ) { + return ''; + } + + return ' ' . \Html::rawElement( + 'span', + [ + 'title' => $property->getCanonicalLabel() + ], + '<sup>ᵖ</sup>' + ); + } + + private function findTranslatedPropertyLabel( $property ) { + + // User-defined properties don't have any translatable label (this is + // what the preferred label is for) + if ( $property->isUserDefined() ) { + return ''; + } + + $prefix = ''; + + if ( $property->isInverse() ) { + $prefix = '-'; + } + + return $prefix . ApplicationFactory::getInstance()->getPropertyLabelFinder()->findPropertyLabelFromIdByLanguageCode( + $property->getKey(), + $this->dataValue->getOption( PropertyValue::OPT_USER_LANGUAGE ) + ); + } + +} |