Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report similarity on property labels #2244

Merged
merged 1 commit into from Feb 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 17 additions & 0 deletions DefaultSettings.php
Expand Up @@ -1394,4 +1394,21 @@
'smwgEditProtectionRight' => false,
##

##
# Similarity lookup exemption property
#
# The listed property is used to exclude a property from the similarity
# lookup in case the comparing property contains an annotation value with the
# exemption property.
#
# For example, the property `Governance level` may define
# [[owl:differentFrom::Governance level of]] which would result in a suppressed
# similarity lookup for both `Governance level` and `Governance level of`
# property when compared to each other.
#
# @since 2.5
##
'smwgSimilarityLookupExemptionProperty' => 'owl:differentFrom',
##

);
7 changes: 7 additions & 0 deletions i18n/en.json
Expand Up @@ -217,6 +217,7 @@
"smw-ask-query-search-info": "The query <code><nowiki>$1</nowiki></code> was answered by the {{PLURAL:$3|1=<code>$2</code> (from cache)|<code>$2</code> (from cache)|<code>$2</code>}} in $4 {{PLURAL:$4|second|seconds}}.",
"searchbyproperty": "Search by property",
"processingerrorlist": "Processing error list",
"propertylabelsimilarity": "Property label similarity report",
"smw-processingerrorlist-intro": "The following list provides an overview about the processing errors that appeared in connection with [https://www.semantic-mediawiki.org/ Semantic MediaWiki]. It is recommended to monitor this list on a regular basis and correct invalid value annotations.",
"smw_sbv_docu": "Search for all pages that have a given property and value.",
"smw_sbv_novalue": "Enter a valid value for the property, or view all property values for \"$1\".",
Expand Down Expand Up @@ -303,6 +304,12 @@
"smw-admin-supplementary-operational-statistics-intro": "<u>$1</u> displays an extended set of statistics",
"smw-admin-supplementary-idlookup-title": "Object ID lookup and disposal",
"smw-admin-supplementary-idlookup-intro": "<u>$1</u> contains functions to lookup and dispose individual ID's",
"smw-property-label-similarity-title": "Property label similarity report",
"smw-property-label-similarity-intro": "<u>$1</u> calculates similarties for existing property labels",
"smw-property-label-similarity-threshold": "Threshold:",
"smw-property-label-similarity-type": "Display Type ID",
"smw-property-label-similarity-noresult": "No results were found for the selected options.",
"smw-property-label-similarity-docu": "Compares and reports the [https://www.semantic-mediawiki.org/wiki/Property_similarity syntactic similarity] (not the semantic similarity) between two property labels which may help filter misspelled or equivalent properties that represent the same concept (see [[Special:Properties]] to clarify concept and usage of reported properties). The threshold can be adjusted to widen or narrow the similarity distance and <code>[[Property:$1|$1]]</code> is set to be used to exempt properties from the process.",
"smw-admin-operational-statistics": "This page contains operational statistics collected in or from Semantic MediaWiki related functions. An extended list of wiki specific statistics can be found [[Special:Statistics|<b>here</b>]].",
"smw_adminlinks_datastructure": "Data structure",
"smw_adminlinks_displayingdata": "Data display",
Expand Down
1 change: 1 addition & 0 deletions i18n/extra/SemanticMediaWiki.alias.php
Expand Up @@ -22,6 +22,7 @@
'SMWAdmin' => array( 'SemanticMediaWiki', 'SMWAdmin' ),
'SearchByProperty' => array( 'SearchByProperty' ),
'ProcessingErrorList' => array( 'ProcessingErrorList' ),
'PropertyLabelSimilarity' => array( 'PropertyLabelSimilarity' ),
'SemanticStatistics' => array( 'SemanticStatistics' ),
'Types' => array( 'Types' ),
'URIResolver' => array( 'URIResolver' ),
Expand Down
1 change: 1 addition & 0 deletions includes/Settings.php
Expand Up @@ -162,6 +162,7 @@ public static function newFromGlobals() {
'smwgQueryResultNonEmbeddedCacheLifetime' => $GLOBALS['smwgQueryResultNonEmbeddedCacheLifetime'],
'smwgQueryResultCacheRefreshOnPurge' => $GLOBALS['smwgQueryResultCacheRefreshOnPurge'],
'smwgEditProtectionRight' => $GLOBALS['smwgEditProtectionRight'],
'smwgSimilarityLookupExemptionProperty' => $GLOBALS['smwgSimilarityLookupExemptionProperty']
);

\Hooks::run( 'SMW::Config::BeforeCompletion', array( &$configuration ) );
Expand Down
4 changes: 4 additions & 0 deletions includes/Setup.php
Expand Up @@ -287,6 +287,10 @@ private function registerSpecialPages() {
'page' => 'SMW\MediaWiki\Specials\SpecialProcessingErrorList',
'group' => 'smw_group'
),
'PropertyLabelSimilarity' => array(
'page' => 'SMW\MediaWiki\Specials\SpecialPropertyLabelSimilarity',
'group' => 'smw_group'
),
'SMWAdmin' => array(
'page' => 'SMW\MediaWiki\Specials\SpecialAdmin',
'group' => 'smw_group'
Expand Down
24 changes: 15 additions & 9 deletions src/MediaWiki/Renderer/HtmlFormRenderer.php
Expand Up @@ -380,7 +380,7 @@ public function addOptionSelectList( $label, $inputName, $inputValue, $options,
*
* @return HtmlFormRenderer
*/
public function addCheckbox( $label, $inputName, $inputValue, $isChecked = false, $id = null ) {
public function addCheckbox( $label, $inputName, $inputValue, $isChecked = false, $id = null, $attributes = array() ) {

if ( $id === null ) {
$id = $inputName;
Expand All @@ -396,10 +396,11 @@ public function addCheckbox( $label, $inputName, $inputValue, $isChecked = false
array(
'id' => $id,
'class' => $this->defaultPrefix . '-checkbox',
'value' => $inputValue ) + ( $isChecked ? array( 'checked' => 'checked' ) : array() )
'value' => $inputValue
) + ( $isChecked ? array( 'checked' => 'checked' ) : array() )
);

$this->content[] = $html;
$this->content[] = Html::rawElement( 'span', $attributes, $html );
return $this;
}

Expand All @@ -409,21 +410,26 @@ public function addCheckbox( $label, $inputName, $inputValue, $isChecked = false
* @note Encapsulate as closure to ensure that the build contains all query
* parameters that are necessary to build the paging links
*
* @param integer $limit,
* @param integer $offset,
* @param integer $count,
* @param integer $limit
* @param integer $offset
* @param integer $count
* @param integer|null $messageCount
*
* @return HtmlFormRenderer
*/
public function addPaging( $limit, $offset, $count ) {
public function addPaging( $limit, $offset, $count, $messageCount = null ) {

$title = $this->title;

$this->content[] = function( $instance ) use ( $title, $limit, $offset, $count ) {
$this->content[] = function( $instance ) use ( $title, $limit, $offset, $count, $messageCount ) {

if ( $messageCount === null ) {
$messageCount = ( $count > $limit ? $count - 1 : $count );
}

$resultCount = $instance->getMessageBuilder()
->getMessage( 'showingresults' )
->numParams( ( $count > $limit ? $count - 1 : $count ), $offset + 1 )
->numParams( $messageCount, $offset + 1 )
->parse();

$paging = $instance->getMessageBuilder()->prevNextToText(
Expand Down
130 changes: 130 additions & 0 deletions src/MediaWiki/Specials/PropertyLabelSimilarity/ContentsBuilder.php
@@ -0,0 +1,130 @@
<?php

namespace SMW\MediaWiki\Specials\PropertyLabelSimilarity;

use SMW\MediaWiki\Renderer\HtmlFormRenderer;
use SMW\Message;
use SMW\RequestOptions;
use SMW\SQLStore\Lookup\PropertyLabelSimilarityLookup;
use Html;

/**
* @license GNU GPL v2+
* @since 2.5
*
* @author mwjames
*/
class ContentsBuilder {

/**
* @var PropertyLabelSimilarityLookup
*/
private $propertyLabelSimilarityLookup;

/**
* @var HtmlFormRenderer
*/
private $htmlFormRenderer;

/**
* @since 2.5
*
* @param PropertyLabelSimilarityLookup $propertyLabelSimilarityLookup
* @param HtmlFormRenderer $htmlFormRenderer
*/
public function __construct( PropertyLabelSimilarityLookup $propertyLabelSimilarityLookup, HtmlFormRenderer $htmlFormRenderer ) {
$this->propertyLabelSimilarityLookup = $propertyLabelSimilarityLookup;
$this->htmlFormRenderer = $htmlFormRenderer;
}

/**
* @since 2.5
*
* @param RequestOptions $requestOption
*/
public function getHtml( RequestOptions $requestOptions ) {

$threshold = 90;
$type = '';

foreach ( $requestOptions->getExtraConditions() as $extraCondition ) {
if ( isset( $extraCondition['type'] ) ) {
$type = $extraCondition['type'];
}

if ( isset( $extraCondition['threshold'] ) ) {
$threshold = $extraCondition['threshold'];
}
}

$this->propertyLabelSimilarityLookup->setThreshold(
$threshold
);

$result = $this->propertyLabelSimilarityLookup->compareAndFindLabels(
$requestOptions
);

$count = $this->propertyLabelSimilarityLookup->getLookupCount();

$html = $this->getForm(
$requestOptions->getLimit(),
$requestOptions->getOffset(),
$count,
count( $result ),
$threshold,
$type
);

if ( $result !== array() ) {
$html .= '<pre>' . json_encode( $result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) . '</pre>';
} else {
$html .= Message::get( 'smw-property-label-similarity-noresult' );
}

return $html;
}

private function getForm( $limit, $offset, $count, $resultCount, $threshold, $type ) {

$exemptionProperty = $this->propertyLabelSimilarityLookup->getExemptionProperty();

$html = Message::get( array( 'smw-property-label-similarity-docu', $exemptionProperty ), Message::PARSE );

$html .= $this->htmlFormRenderer
->setName( 'smw-property-label-similarity-title' )
->setMethod( 'get' )
->withFieldset()
->addPaging(
$limit,
$offset,
$count,
$resultCount )
->addHiddenField( 'limit', $limit )
->addHiddenField( 'offset', $offset )
->addInputField(
Message::get( 'smw-property-label-similarity-threshold' ),
'threshold',
$threshold,
'',
5
)
->addNonBreakingSpace()
->addCheckbox(
Message::get( 'smw-property-label-similarity-type', Message::ESCAPED ),
'type',
'yes',
$type === 'yes',
null,
array(
'style' => 'float:right'
)
)
->addQueryParameter( 'type', $type )
->addSubmitButton( Message::get( 'allpagessubmit' ) )
->getForm();

return Html::rawElement( 'div', array( 'class' => 'plainlinks'), $html ) . Html::element( 'p', array(), '' );
}

}
2 changes: 1 addition & 1 deletion src/MediaWiki/Specials/SpecialAdmin.php
Expand Up @@ -77,7 +77,7 @@ public function execute( $query ) {
$idActionHandler,
$supportWidget
) = $this->getHandlers(
$applicationFactory->getStore(),
$applicationFactory->getStore( '\SMW\SQLStore\SQLStore' ),
$applicationFactory->getSettings(),
$applicationFactory->newMwCollaboratorFactory()
);
Expand Down
87 changes: 87 additions & 0 deletions src/MediaWiki/Specials/SpecialPropertyLabelSimilarity.php
@@ -0,0 +1,87 @@
<?php

namespace SMW\MediaWiki\Specials;

use SMW\ApplicationFactory;
use SpecialPage;
use SMW\Message;
use SMW\SQLStore\Lookup\PropertyLabelSimilarityLookup;
use SMW\MediaWiki\Specials\PropertyLabelSimilarity\ContentsBuilder;

/**
* @license GNU GPL v2+
* @since 2.5
*
* @author mwjames
*/
class SpecialPropertyLabelSimilarity extends SpecialPage {

/**
* @codeCoverageIgnore
*/
public function __construct() {
parent::__construct( 'PropertyLabelSimilarity' );
}

/**
* @see SpecialPage::execute
*/
public function execute( $query ) {

$this->setHeaders();
$output = $this->getOutput();
$webRequest = $this->getRequest();

$store = ApplicationFactory::getInstance()->getStore( '\SMW\SQLStore\SQLStore' );

$propertyLabelSimilarityLookup = new PropertyLabelSimilarityLookup(
$store
);

$propertyLabelSimilarityLookup->setExemptionProperty(
ApplicationFactory::getInstance()->getSettings()->get( 'smwgSimilarityLookupExemptionProperty' )
);

$htmlFormRenderer = ApplicationFactory::getInstance()->newMwCollaboratorFactory()->newHtmlFormRenderer(
$this->getContext()->getTitle(),
$this->getLanguage()
);

$contentsBuilder = new ContentsBuilder(
$propertyLabelSimilarityLookup,
$htmlFormRenderer
);

$threshold = (int)$webRequest->getText( 'threshold', 90 );
$type = $webRequest->getText( 'type', false );

$offset = (int)$webRequest->getText( 'offset', 0 );
$limit = (int)$webRequest->getText( 'limit', 50 );

$requestOptions = ApplicationFactory::getInstance()->getQueryFactory()->newRequestOptions();
$requestOptions->setLimit( $limit );
$requestOptions->setOffset( $offset );

$requestOptions->addExtraCondition(
array(
'type' => $type,
'threshold' => $threshold
)
);

$output->addHtml(
$contentsBuilder->getHtml( $requestOptions )
);

return true;
}


/**
* @see SpecialPage::getGroupName
*/
protected function getGroupName() {
return 'smw_group';
}

}