r113994 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r113993‎ | r113994 | r113995 >
Date:03:18, 16 March 2012
Author:danwe
Status:new
Tags:
Comment:
New extension 'Semantic Expressiveness', early ALPHA
*** NOT READY FOR TRANSLATION ***
Modified paths:
  • /trunk/extensions/SemanticExpressiveness (added) (history)
  • /trunk/extensions/SemanticExpressiveness/COPYING (added) (history)
  • /trunk/extensions/SemanticExpressiveness/README (added) (history)
  • /trunk/extensions/SemanticExpressiveness/RELEASE-NOTES (added) (history)
  • /trunk/extensions/SemanticExpressiveness/SemanticExpressiveness.i18n.magic.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/SemanticExpressiveness.i18n.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/SemanticExpressiveness.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveString.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringOutputOptions.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPF.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPiece.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPieceByRegex.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPieceSQ.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPieceSQResult.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPieceWikiLink.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExPFParamsBasedFactory.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExQueryPF.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExShortQuery.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExShortQueryAbstractResult.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExShortQueryOutputOptions.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExShortQueryProcessor.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/SemExShortQueryResult.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/validation (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/validation/SemExCriterionIsProperty.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/validation/SemExCriterionIsQuerySource.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/validation/SemExParamManipulationProperty.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/includes/validation/SemExParamManipulationQuerySource.php (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.ShortQueryResult.js (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.css (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.js (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ContextPopup.css (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ContextPopup.js (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.InlineMeasurer.js (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ShortQueryHover.Cache.js (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ShortQueryHover.css (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ShortQueryHover.initialize.js (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ShortQueryHover.js (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.TitledContextPopup.css (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.TitledContextPopup.js (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.js (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/images (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/images/pointer-down-titledpopup.png (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/images/pointer-down.png (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/images/pointer-up-titledpopup.png (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/images/pointer-up.png (added) (history)
  • /trunk/extensions/SemanticExpressiveness/resources/images/pointer.psd (added) (history)

Diff [purge]

Index: trunk/extensions/SemanticExpressiveness/SemanticExpressiveness.php
@@ -0,0 +1,193 @@
 2+<?php
 3+
 4+/**
 5+ * 'Semantic Expressiveness' introduces a short hand query syntax to query single values from the
 6+ * same or another page. It aims to further reduce redundancy and to make wikitext and query
 7+ * outputs more expressive by adding information where queried values come from.
 8+ *
 9+ * Documentation: https://www.mediawiki.org/wiki/Extension:Semantic_Expressiveness
 10+ * Support: https://www.mediawiki.org/wiki/Extension_talk:Semantic_Expressiveness
 11+ * Source code: https://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/SemanticExpressiveness
 12+ *
 13+ * @version: 0.1 alpha
 14+ * @license: ISC License
 15+ * @author: Daniel Werner < danweetz@web.de >
 16+ *
 17+ * @file SemanticExpressiveness.php
 18+ * @ingroup SemanticExpressiveness
 19+ */
 20+
 21+if( !defined( 'MEDIAWIKI' ) ) { die(); }
 22+
 23+$wgExtensionCredits[ defined( 'SEMANTIC_EXTENSION_TYPE' ) ? 'semantic' : 'other' ][] = array(
 24+ 'path' => __FILE__,
 25+ 'name' => 'Semantic Expressiveness',
 26+ 'descriptionmsg' => 'semex-desc',
 27+ 'version' => ExtSemEx::VERSION,
 28+ 'author' => '[https://www.mediawiki.org/wiki/User:Danwe Daniel Werner]',
 29+ 'url' => 'https://www.mediawiki.org/wiki/Extension:Semantic_Expressiveness',
 30+);
 31+
 32+$wgHooks['ParserFirstCallInit' ][] = 'ExtSemEx::init';
 33+
 34+// language files:
 35+$wgExtensionMessagesFiles['SemEx' ] = ExtSemEx::getDir() . '/SemanticExpressiveness.i18n.php';
 36+$wgExtensionMessagesFiles['SemExMagic'] = ExtSemEx::getDir() . '/SemanticExpressiveness.i18n.magic.php';
 37+
 38+// resources inclusion:
 39+ExtSemEx::registerResourceModules();
 40+$wgHooks['OutputPageParserOutput'][] = 'ExtSemEx::onOutputPageParserOutput';
 41+$wgHooks['InternalParseBeforeSanitize'][] = 'ExtSemEx::onInternalParseBeforeSanitize';
 42+
 43+
 44+$incDir = ExtSemEx::getDir() . '/includes/';
 45+
 46+// general inclusions:
 47+$wgAutoloadClasses['SemExExpressiveString' ] = $incDir . 'SemExExpressiveString.php';
 48+$wgAutoloadClasses['SemExExpressiveStringPiece' ] = $incDir . 'SemExExpressiveStringPiece.php';
 49+$wgAutoloadClasses['SemExExpressiveStringPieceByRegex' ] = $incDir . 'SemExExpressiveStringPieceByRegex.php';
 50+$wgAutoloadClasses['SemExExpressiveStringPieceSQ' ] = $incDir . 'SemExExpressiveStringPieceSQ.php';
 51+$wgAutoloadClasses['SemExExpressiveStringPieceSQResult'] = $incDir . 'SemExExpressiveStringPieceSQResult.php';
 52+$wgAutoloadClasses['SemExExpressiveStringPieceWikiLink'] = $incDir . 'SemExExpressiveStringPieceWikiLink.php';
 53+$wgAutoloadClasses['SemExExpressiveStringOutputOptions'] = $incDir . 'SemExExpressiveStringOutputOptions.php';
 54+$wgAutoloadClasses['SemExQueryPF' ] = $incDir . 'SemExQueryPF.php';
 55+$wgAutoloadClasses['SemExShortQuery' ] = $incDir . 'SemExShortQuery.php';
 56+$wgAutoloadClasses['SemExShortQueryProcessor' ] = $incDir . 'SemExShortQueryProcessor.php';
 57+$wgAutoloadClasses['SemExShortQueryResult' ] = $incDir . 'SemExShortQueryResult.php';
 58+$wgAutoloadClasses['SemExShortQueryAbstractResult' ] = $incDir . 'SemExShortQueryAbstractResult.php';
 59+$wgAutoloadClasses['SemExShortQueryOutputOptions' ] = $incDir . 'SemExShortQueryOutputOptions.php';
 60+$wgAutoloadClasses['SemExPFParamsBasedFactory' ] = $incDir . 'SemExPFParamsBasedFactory.php';
 61+
 62+// validator stuff:
 63+$wgAutoloadClasses['SemExCriterionIsProperty' ] = $incDir . 'validation/SemExCriterionIsProperty.php';
 64+$wgAutoloadClasses['SemExCriterionIsQuerySource' ] = $incDir . 'validation/SemExCriterionIsQuerySource.php';
 65+$wgAutoloadClasses['SemExParamManipulationProperty' ] = $incDir . 'validation/SemExParamManipulationProperty.php';
 66+$wgAutoloadClasses['SemExParamManipulationQuerySource'] = $incDir . 'validation/SemExParamManipulationQuerySource.php';
 67+
 68+// Parser function initializations:
 69+$wgAutoloadClasses['SemExQueryPF' ] = $incDir . 'SemExQueryPF.php';
 70+$wgAutoloadClasses['SemExExpressiveStringPF' ] = $incDir . 'SemExExpressiveStringPF.php';
 71+
 72+$wgHooks['ParserFirstCallInit'][] = 'SemExExpressiveStringPF::staticInit';
 73+
 74+unset( $incDir );
 75+
 76+
 77+define( 'SEMEX_EXPR_PIECE_STRING', SemExExpressiveStringPiece::getType() );
 78+define( 'SEMEX_EXPR_PIECE_SQRESULT', SemExExpressiveStringPieceSQResult::getType() );
 79+define( 'SEMEX_EXPR_PIECE_SQ', SemExExpressiveStringPieceSQ::getType() );
 80+define( 'SEMEX_EXPR_PIECE_WIKILINK', SemExExpressiveStringPieceWikiLink::getType() );
 81+
 82+
 83+class ExtSemEx {
 84+
 85+ const VERSION = '0.1 alpha';
 86+
 87+ static function init( &$parser ) {
 88+ $parser->setFunctionHook( '?', array( 'SemExQueryPF', 'render' ), SFH_NO_HASH );
 89+ //$parser->setFunctionHook( '?!', array( 'SemExPlainQueryPF', 'render' ), SFH_NO_HASH );
 90+ $parser->setFunctionHook( '?to?!', __CLASS__ . '::parserFunc_QueryToPlainQuery', SFH_NO_HASH );
 91+ return true;
 92+ }
 93+
 94+ /**
 95+ * Returns the extensions base installation directory.
 96+ * @return string
 97+ */
 98+ public static function getDir() {
 99+ static $dir = null;
 100+ if( $dir === null ) {
 101+ $dir = dirname( __FILE__ );
 102+ }
 103+ return $dir;
 104+ }
 105+
 106+ /**
 107+ * Get the RPG-Dev-Tools installation directory path as seen from the web.
 108+ * @return string
 109+ */
 110+ public static function getScriptPath() {
 111+ static $path = null;
 112+ if( $path === null ) {
 113+ global $wgVersion, $wgScriptPath, $wgExtensionAssetsPath;
 114+
 115+ $dir = str_replace( '\\', '/', self::getDir() );
 116+ $dirName = substr( $dir, strrpos( $dir, '/' ) + 1 );
 117+
 118+ $path = (
 119+ ( version_compare( $wgVersion, '1.16', '>=' ) && isset( $wgExtensionAssetsPath ) && $wgExtensionAssetsPath )
 120+ ? $wgExtensionAssetsPath
 121+ : $wgScriptPath . '/extensions'
 122+ ) . "/$dirName";
 123+ }
 124+ return $path;
 125+ }
 126+
 127+ /**
 128+ * Registers JavaScript and CSS to ResourceLoader.
 129+ */
 130+ public static function registerResourceModules() {
 131+ global $wgResourceModules;
 132+
 133+ $moduleTemplate = array(
 134+ 'localBasePath' => self::getDir(),
 135+ 'remoteBasePath' => self::getScriptPath(),
 136+ 'group' => 'ext.semex'
 137+ );
 138+ $wgResourceModules['ext.semex'] = $moduleTemplate + array(
 139+ 'scripts' => array(
 140+ 'resources/ext.semex.js',
 141+ 'resources/ext.semex.ShortQueryResult.js',
 142+ 'resources/ext.semex.ui.js',
 143+ 'resources/ext.semex.ui.InlineMeasurer.js',
 144+ 'resources/ext.semex.ui.ContextPopup.js',
 145+ 'resources/ext.semex.ui.TitledContextPopup.js',
 146+ 'resources/ext.semex.ui.ShortQueryHover.js',
 147+ 'resources/ext.semex.ui.ShortQueryHover.Cache.js',
 148+ 'resources/ext.semex.ui.ShortQueryHover.initialize.js',
 149+ ),
 150+ 'styles' => array(
 151+ 'resources/ext.semex.css',
 152+ 'resources/ext.semex.ui.ContextPopup.css',
 153+ 'resources/ext.semex.ui.TitledContextPopup.css',
 154+ 'resources/ext.semex.ui.ShortQueryHover.css',
 155+ ),
 156+ 'messages' => array(
 157+ 'semex-shortquery-title',
 158+ 'semex-shortquery-hover-loading',
 159+ 'semex-shortquery-hover-loading-failed'
 160+ ),
 161+ );
 162+ }
 163+
 164+ public static function onOutputPageParserOutput() {
 165+ // load CSS and JavaScript
 166+ // we can't add this just within SemExShortQueryResult since it's possible to get a
 167+ // short query result from another page which is stored within a SMW property!
 168+ global $wgOut;
 169+ $wgOut->addModules( 'ext.semex' );
 170+ return true;
 171+ }
 172+
 173+ /*
 174+ * NOTE: this hook requires the fix for bug #34678, https://bugzilla.wikimedia.org/show_bug.cgi?id=34678
 175+ */
 176+ public static function onInternalParseBeforeSanitize( Parser &$parser, &$text ) {
 177+ $exprString = new SemExExpressiveString( $text, $parser, SEMEX_EXPR_PIECE_SQ );
 178+ $text = $exprString->getWikiText();
 179+
 180+ /*
 181+ * Sanitize the whole thing, otherwise HTML and JS code injection would be possible.
 182+ * Basically the same is happening in Parser::internalParse() right before 'InternalParseBeforeLinks' hook is called.
 183+ */
 184+ /*
 185+ $text = Sanitizer::removeHTMLtags(
 186+ $text,
 187+ array( &$parser, 'attributeStripCallback' ),
 188+ false,
 189+ array_keys( $parser->mTransparentTagHooks )
 190+ );
 191+ */
 192+ return true;
 193+ }
 194+}
Property changes on: trunk/extensions/SemanticExpressiveness/SemanticExpressiveness.php
___________________________________________________________________
Added: svn:eol-style
1195 + native
Index: trunk/extensions/SemanticExpressiveness/RELEASE-NOTES
@@ -0,0 +1,15 @@
 2+ 'Semantic Expressiveness' Changelog:
 3+ =====================================
 4+
 5+ * Version 0.1 alpha
 6+ ~~ THIS IS NOT A FINAL RELEASE YET ~~
 7+
 8+ - Syntax for so called inline short queries, basically "<?property::page>" with a few advanced
 9+ syntactical features like nested "<?A::<?B::page>>" or "<?A::B::page>". This syntax is getting
 10+ parsed after template execution and fully respects nowiki, noincude, comments, pre and others.
 11+ - Parser function version of the new syntax called "?" with advanced parameters.
 12+ - Extensive JavaScript allowing to display information from a short queries source page like the
 13+ pages fact box or any other content. Might need some configuration for custom wiki adjustment.
 14+ - "?to?!" (might be renamed later) parser function allowing to parse the short query syntax early
 15+ to give template programmers full control.
 16+ - "SemExExpressiveString" class, extendable parser for the new syntax, also recognizes wikilinks.
\ No newline at end of file
Index: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPiece.php
@@ -0,0 +1,290 @@
 2+<?php
 3+
 4+/**
 5+ * Class representing one piece of a SemExExpressiveString.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SemExExpressiveStringPiece.php
 10+ * @ingroup SemanticExpressiveness
 11+ *
 12+ * @author Daniel Werner < danweetz@web.de >
 13+ */
 14+class SemExExpressiveStringPiece {
 15+
 16+ protected $value;
 17+
 18+ /**
 19+ * Constructor
 20+ *
 21+ * @param mixed $value
 22+ */
 23+ function __construct( $value ) {
 24+ $this->value = $value;
 25+ }
 26+
 27+ /**
 28+ * Returns the value of this piece
 29+ *
 30+ * @return mixed depending on the pieces type
 31+ */
 32+ public function getValue() {
 33+ return $this->value;
 34+ }
 35+
 36+ /**
 37+ * Returns the raw text value of this piece. Doesn't contain any expressive markup anymore,
 38+ * just its textual representation. If there is no textual representation, this will return
 39+ * an empty string even though the actual textual representation could be an empty string.
 40+ * static::isUnresolvable() can be used to make sure whether any textual representation is
 41+ * available.
 42+ *
 43+ * @return string
 44+ */
 45+ public function getRawText() {
 46+ return $this->value;
 47+ }
 48+
 49+ /**
 50+ * Same as getRawText() but potentially with more expensive markup for wiki text usage.
 51+ *
 52+ * @return string
 53+ */
 54+ public function getWikiText(
 55+ $linked = SemExExpressiveStringOutputOptions::LINK_ALL,
 56+ $showErrors = false
 57+ ) {
 58+ return $this->value;
 59+ }
 60+
 61+ /**
 62+ * Returns an abstract textual representation of this pieces meaning. If the type doesn't
 63+ * support abstract representation, this will return the normal raw text.
 64+ *
 65+ * @return string
 66+ */
 67+ public function getAbstractRawText() {
 68+ return $this->getRawText();
 69+ }
 70+
 71+ /**
 72+ * Returns the abstract wiki text representation of this piece. If the type doesn't support
 73+ * abstract representation, this will return the normal wiki text.
 74+ *
 75+ * @return string
 76+ */
 77+ public function getAbstractWikiText(
 78+ $linked = SemExExpressiveStringOutputOptions::LINK_ALL,
 79+ $showErrors = false
 80+ ) {
 81+ return $this->getWikiText( $linked, $showErrors );
 82+ }
 83+
 84+ /**
 85+ * Returns the output of the piece in a form specified by a SemExExpressiveStringOutputOptions
 86+ * object.
 87+ *
 88+ * @param SemExExpressiveStringOutputOptions $options
 89+ * @return string
 90+ */
 91+ public final function getOutput( SemExExpressiveStringOutputOptions $options ) {
 92+ // make sure that the output options object contains all options which might be expected by
 93+ // any overridden ancestor class function.
 94+ $dfltOptions = $this->getDefaultOutputOptions();
 95+
 96+ if( get_class( $options ) !== get_class( $dfltOptions ) ) {
 97+ $dfltOptions->mergeOptions( $options );
 98+ $options = $dfltOptions;
 99+ }
 100+ return $this->getOutputByOptions( $options );
 101+ }
 102+
 103+ /**
 104+ * This is the function handling getOutput() internally, receiving ab appropriate instance of
 105+ * 'SemExExpressiveStringOutputOptions' or rather of the subclass describing all options for
 106+ * the piece type.
 107+ * It is datermined by getDefaultOutputOptions() which one would be the most suitable
 108+ * 'SemExExpressiveStringOutputOptions' subclass for this type.
 109+ *
 110+ * @param SemExExpressiveStringOutputOptions $options
 111+ * @return string
 112+ */
 113+ protected function getOutputByOptions( SemExExpressiveStringOutputOptions $options ) {
 114+ $useRaw = $options->getFormat() === SemExExpressiveStringOutputOptions::FORMAT_RAW;
 115+ $linked = $options->getLink();
 116+ $errors = $options->getShowErrors();
 117+
 118+ if( $options->getShowAbstract() === SemExExpressiveStringOutputOptions::ABSTRACT_ONLY
 119+ || $options->getShowAbstract() === SemExExpressiveStringOutputOptions::ABSTRACT_IF_FAILURE
 120+ && $this->isUnresolvable()
 121+ ) {
 122+ if( $useRaw ) {
 123+ return $this->getAbstractRawText();
 124+ } else {
 125+ return $this->getAbstractWikiText( $linked, $errors );
 126+ }
 127+ } else {
 128+ if( $useRaw ) {
 129+ return $this->getRawText();
 130+ } else {
 131+ return $this->getWikiText( $linked, $errors );
 132+ }
 133+ }
 134+ }
 135+
 136+ /**
 137+ * Returns true if the expressive meaning can't be resolved into a textual representation.
 138+ *
 139+ * @return bool
 140+ */
 141+ public function isUnresolvable() {
 142+ return false;
 143+ }
 144+
 145+ /**
 146+ * Returns whether there have occurred errors of any kind.
 147+ *
 148+ * @return bool
 149+ */
 150+ public function hasErrors() {
 151+ $errors = $this->getErrors();
 152+ return !empty( $errors );
 153+ }
 154+
 155+ /**
 156+ * Returns all errors occurred so far
 157+ * Note that this will return true if isUnresolvable() is true, even though this cann still
 158+ * have an abstract representation instead.
 159+ *
 160+ * @return string[]
 161+ */
 162+ public final function getErrors() {
 163+ $errors = $this->getErrors_internal();
 164+ if( $this->isUnresolvable() ) {
 165+ $errors = array_merge( array( 'semex-expressivestring-unresolvable' ), $errors );
 166+ }
 167+ return $errors;
 168+ }
 169+
 170+ /**
 171+ * Function to gather errors from the internal $value. Use this rather than overwriting getErrors()
 172+ *
 173+ * @return string[]
 174+ */
 175+ protected function getErrors_internal() {
 176+ return array();
 177+ }
 178+
 179+ /**
 180+ * Returns whether this piece type has a meaningful abstract representation.
 181+ *
 182+ * @return bool
 183+ */
 184+ public static function hasAbstractRepresentation() {
 185+ return false;
 186+ }
 187+
 188+ /**
 189+ * Returns what kind of piece of an expressive string this is.
 190+ *
 191+ * @return string
 192+ */
 193+ public static function getType() {
 194+ return get_called_class();
 195+ }
 196+
 197+ /**
 198+ * Returns an instance of SemExExpressiveStringOutputOptions (or a descendant class engineered for
 199+ * this specific piece type) which holds the default output options.
 200+ *
 201+ * @return SemExExpressiveStringOutputOptions
 202+ */
 203+ public static function getDefaultOutputOptions() {
 204+ return new SemExExpressiveStringOutputOptions();
 205+ }
 206+
 207+ /**
 208+ * Whether or not this piece has a expressive meaning, basically this is true if this is not a
 209+ * simple string.
 210+ *
 211+ * @return bool
 212+ */
 213+ public static function isExpressive() {
 214+ // will return true for inherited classes but still allows them to overwrite.
 215+ return ( static::getType() !== SEMEX_EXPR_PIECE_STRING );
 216+ }
 217+
 218+ /**
 219+ * This will initialize the piece type within a existing SemExExpressiveString object by examining
 220+ * its non-expressive parts for expressive meaning.
 221+ *
 222+ * @param SemExExpressiveString $target
 223+ */
 224+ public static function initWithin( SemExExpressiveString $target ) {
 225+ if( ! static::isExpressive() ) {
 226+ // unnecessary to examine a non-expressive meaning just to end up with the same!
 227+ return;
 228+ }
 229+ $i = -1;
 230+ foreach( $target->getPieces() as $piece ) {
 231+ $i++;
 232+ $newPieces = static::examinePiece( $piece, $target->getParser() );
 233+ if( $newPieces === false ) {
 234+ // no meaning in this context
 235+ continue;
 236+ }
 237+
 238+ // replace old piece with its new resolved meaning:
 239+ $target->removePieces( $i, 1 );
 240+ $target->addPieces( $newPieces, $i );
 241+
 242+ $i += count( $newPieces ) - 1;
 243+ }
 244+ }
 245+
 246+ /**
 247+ * Examines a string or a SemExExpressiveStringPiece about whether it does match this piece type
 248+ * and returns an array with this type of piece detected and non-expressive information as normal
 249+ * SemExExpressiveStringPiece objects. Returns false if nothing detected.
 250+ *
 251+ * @param string|SemExExpressiveStringPiece $piece
 252+ * @param Parser $parser
 253+ * @return SemExExpressiveStringPiece[]|false
 254+ */
 255+ public final static function examinePiece( $piece, Parser $parser ) {
 256+ if( ! $piece->isExpressive() ) {
 257+ $piece = $piece->getRawText();
 258+ }
 259+ if( is_string( $piece ) ) {
 260+ return static::examineString( $piece, $parser );
 261+ }
 262+
 263+ return static::examineExpressivePiece( $piece, $parser );
 264+ }
 265+
 266+ /**
 267+ * Examines a string for expressive meaning matching this piece type and returns an array
 268+ * with this type of piece detected and non-expressive information as normal
 269+ * SemExExpressiveStringPiece objects. Returns false if nothing detected.
 270+ *
 271+ * @param string $string
 272+ * @param Parser $parser
 273+ * @return SemExExpressiveStringPiece[]|false
 274+ */
 275+ protected static function examineString( $string, Parser $parser ) {
 276+ return false;
 277+ }
 278+
 279+ /**
 280+ * Examines an piece which already has its expressive meaning detected for further meaning
 281+ * matching this type and returns an array of detected pieces. Returns false if nothing
 282+ * detected.
 283+ *
 284+ * @param SemExExpressiveStringPiece $piece
 285+ * @param Parser $parser
 286+ * @return SemExExpressiveStringPiece[]|false
 287+ */
 288+ protected static function examineExpressivePiece( SemExExpressiveStringPiece $piece, Parser $parser ) {
 289+ return false;
 290+ }
 291+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPiece.php
___________________________________________________________________
Added: svn:eol-style
1292 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExQueryPF.php
@@ -0,0 +1,65 @@
 2+<?php
 3+
 4+/**
 5+ * Class for '?' short query parser function
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SemExQueryPF.php
 10+ * @ingroup SemanticExpressiveness
 11+ *
 12+ * @author Daniel Werner < danweetz@web.de >
 13+ */
 14+
 15+class SemExQueryPF {
 16+
 17+ public static function render( Parser &$parser ) {
 18+ global $smwgQEnabled, $smwgIQRunningNumber;
 19+
 20+ if ( $smwgQEnabled ) {
 21+ $smwgIQRunningNumber++;
 22+
 23+ $params = func_get_args();
 24+ array_shift( $params ); // remove $parser
 25+
 26+ $query = SemExShortQuery::newFromPFParams(
 27+ $params,
 28+ array( 'property', Validator::PARAM_UNNAMED )
 29+ );
 30+ $options = SemExShortQueryOutputOptions::newFromPFParams( $params );
 31+
 32+ if( ! $query || ! $options ) {
 33+ // @ToDo: real error message (anyway, in what case can this happen?)
 34+ return 'FALSE';
 35+ }
 36+
 37+ $result = SemExShortQueryProcessor::getResultFromQuery( $parser, $query, $options );
 38+ } else {
 39+ $result = smwfEncodeMessages( array( wfMsgForContent( 'smw_iq_disabled' ) ) );
 40+ }
 41+
 42+ return $result;
 43+ }
 44+
 45+ /**
 46+ * Returns a description of all allowed function Parameters.
 47+ *
 48+ * @return array
 49+ */
 50+ public static function getParameters() {
 51+ $params = array();
 52+
 53+ $params['intro'] = new Parameter( 'intro' );
 54+ $params['outro'] = new Parameter( 'outro' );
 55+ $params['default'] = new Parameter( 'default' );
 56+
 57+ // add function parameters describing the querry and its options:
 58+ $params = array_merge(
 59+ $params,
 60+ SemExShortQuery::getPFParams(),
 61+ SemExShortQueryOutputOptions::getPFParams()
 62+ );
 63+
 64+ return $params;
 65+ }
 66+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExQueryPF.php
___________________________________________________________________
Added: svn:eol-style
167 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPieceWikiLink.php
@@ -0,0 +1,83 @@
 2+<?php
 3+
 4+/**
 5+ * Class representing one piece of a SemExExpressiveString representing a wiki link.
 6+ * This represents all kinds of wiki links, also category links and SMW property declarations.
 7+ * This implementation is rather shallow and mainly serves to filter Links.
 8+ *
 9+ * @since 0.1
 10+ *
 11+ * @file SemExExpressiveStringPiece.php
 12+ * @ingroup SemanticExpressiveness
 13+ *
 14+ * @author Daniel Werner < danweetz@web.de >
 15+ */
 16+class SemExExpressiveStringPieceWikiLink extends SemExExpressiveStringPieceByRegex {
 17+
 18+ // Search all kind of wiki links (including category and SMW)
 19+ // $1: ":" if this is a normal link explicitly
 20+ // $2: empty or source
 21+ // $3: text and if $2 is empty also source
 22+ protected static $regex = '\[\[ (:?) ( \s* (?=[^\[\]\|]*\|)[^\[\]\|]* \s* \| | )( [^\[\]]* ) \]\]';
 23+ protected static $regex_modifiers = 'x';
 24+ protected static $regex_essentials = array( true, true, true );
 25+
 26+ protected $isExplicitLink;
 27+ protected $linkTarget;
 28+ protected $linkText;
 29+
 30+ function __construct( array $value ) {
 31+ parent::__construct( $value );
 32+
 33+ $this->isExplicitLink = $value['explicit'];
 34+ $this->linkTarget = $value['target'];
 35+ $this->linkText = $value['text'];
 36+ }
 37+
 38+ /**
 39+ * Returns the link in its raw form as wiki text.
 40+ *
 41+ * @return string
 42+ */
 43+ public function getRawLink() {
 44+ return '[[' . ( $this->isExplicitLink ? ':' : '' ) . $this->linkTarget . $this->linkText . ']]';
 45+ }
 46+
 47+ public function getRawText() {
 48+ return $this->linkText;
 49+ }
 50+
 51+ public function getWikiText(
 52+ $linked = SemExExpressiveStringOutputOptions::LINK_ALL,
 53+ $showErrors = false
 54+ ) {
 55+ if( $linked === SemExExpressiveStringOutputOptions::LINK_ALL ) {
 56+ return $this->getRawLink();
 57+ } else {
 58+ return $this->linkText;
 59+ }
 60+ }
 61+
 62+ public function isUnresolvable() {
 63+ return false;
 64+ }
 65+
 66+ public static function hasAbstractRepresentation() {
 67+ return false;
 68+ }
 69+
 70+ protected static function examineRegexMatch( array $backRefs, Parser $parser ) {
 71+ $result = array();
 72+
 73+ $result['explicit'] = $backRefs[1] === ':';
 74+ $result['text'] = $backRefs[3]; // can contain leading/trailing spaces
 75+ $result['target'] = ( $backRefs[2] !== '' )
 76+ ? $backRefs[2]
 77+ : trim( $result['text'] );
 78+
 79+ // Don't do further checks about whether this is a valid title since this could be
 80+ // SMW property declaration syntax as well
 81+
 82+ return new static( $result );
 83+ }
 84+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPieceWikiLink.php
___________________________________________________________________
Added: svn:eol-style
185 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPieceSQResult.php
@@ -0,0 +1,117 @@
 2+<?php
 3+
 4+/**
 5+ * Class representing one short query result piece of a SemExExpressiveString.
 6+ * Similar to SemExExpressiveStringPieceSQ with the difference that the initialization routines for
 7+ * this type search for the result of an already queried short query within a string.
 8+ *
 9+ * @since 0.1
 10+ *
 11+ * @file SemExExpressiveStringPieceSQResult.php
 12+ * @ingroup SemanticExpressiveness
 13+ *
 14+ * @author Daniel Werner < danweetz@web.de >
 15+ */
 16+class SemExExpressiveStringPieceSQResult extends SemExExpressiveStringPieceByRegex {
 17+
 18+ // [1] match <span> with 'shortQuery' class if we can make sure...
 19+ // [2] ... no further <span>-pairs inside...
 20+ // OR
 21+ // [3] ... DOM inside only contains opening+closing <span>-pairs (ensured by recursive regex)
 22+ protected static $regex = '
 23+ (?# COMMENT #1 )
 24+ <span \s+(?:[^>]*\s+|) class\s*=\s*(?P<q>[\'"])(?:[^>\k<q>]*\s+|\s*) shortQuery (?:[^>\k<q>]*\s+|\s*)\k<q>[^>]*>
 25+
 26+ (?# COMMENT #2 )
 27+ ( (?>(?!<span(?:\s+[^>]*|)>|<\/span>).)*
 28+
 29+ (?# COMMENT #3 )
 30+ | (?P<innerDOM> <span(?:\s+[^>]*|)>(?: (?>(?!<span(?:\s+[^>]*|)>|<\/span>).)* | (?&innerDOM) )*?<\/span> )*
 31+ )* <\/span>';
 32+
 33+ protected static $regex_modifiers = 'sx';
 34+ protected static $regex_essentials = array( false, false );
 35+
 36+ /**
 37+ * @var SemExShortQueryResult
 38+ */
 39+ protected $value;
 40+
 41+ function __construct( SemExShortQueryResult $value ) {
 42+ parent::__construct( $value );
 43+ }
 44+
 45+ public function getRawText() {
 46+ return $this->value->getRawText();
 47+ }
 48+
 49+ public function getWikiText(
 50+ $linked = SemExExpressiveStringOutputOptions::LINK_ALL,
 51+ $showErrors = false
 52+ ) {
 53+ return $this->value->getWikiText( $linked, $showErrors );
 54+ }
 55+
 56+ public function getAbstractRawText() {
 57+ return $this->value->getAbstractResult()->getRawText();
 58+ }
 59+
 60+ public function getAbstractWikiText(
 61+ $linked = SemExExpressiveStringOutputOptions::LINK_ALL,
 62+ $showErrors = false
 63+ ) {
 64+ return $this->value->getAbstractResult()->getWikiText( $linked, $showErrors );
 65+ }
 66+
 67+ public static function hasAbstractRepresentation() {
 68+ return true;
 69+ }
 70+
 71+ public function isUnresolvable() {
 72+ return $this->value->isEmpty();
 73+ }
 74+
 75+ protected function getErrors_internal() {
 76+ return $this->value->getErrors();
 77+ }
 78+
 79+ protected function getOutputByOptions( SemExExpressiveStringOutputOptions $options ) {
 80+ return $this->value->getOutput( $options );
 81+ }
 82+
 83+ /**
 84+ * @return SemExShortQueryOutputOptions
 85+ */
 86+ public static function getDefaultOutputOptions() {
 87+ return new SemExShortQueryOutputOptions();
 88+ }
 89+
 90+ protected static function examineRegexMatch( array $backRefs, Parser $parser ) {
 91+ /*
 92+ $part = str_replace( '&nbsp;', ' ', $part );
 93+ $part = str_replace( '&#32;', ' ', $part );
 94+ $part = str_replace( '&#160;', ' ', $part );
 95+ */
 96+ $xmlDoc = new DOMDocument();
 97+ $xmlDoc->strictErrorChecking = false;
 98+
 99+ wfSuppressWarnings();
 100+ $validDom = $xmlDoc->loadXML( $backRefs[0] );
 101+ wfRestoreWarnings();
 102+
 103+ if( ! $validDom ) {
 104+ // no well-formed xml, insert as plain string
 105+ return false;
 106+ }
 107+
 108+ try {
 109+ // try to re-fabricate short query result from DOM:
 110+ $sqResult = SemExShortQueryResult::newFromDOM( $xmlDoc->documentElement, $parser );
 111+ } catch( Exception $exc ) {
 112+ // invalid, insert as plain string
 113+ return false;
 114+ }
 115+
 116+ return new static( $sqResult );
 117+ }
 118+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPieceSQResult.php
___________________________________________________________________
Added: svn:eol-style
1119 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPieceSQ.php
@@ -0,0 +1,119 @@
 2+<?php
 3+
 4+/**
 5+ * Class representing one short query (sq) piece of a SemExExpressiveString.
 6+ * Similar to SemExExpressiveStringPieceSQResult with the difference that this piece represents a
 7+ * syntax for short to be executed instead of their actual results.
 8+ *
 9+ * Basically, this is the parser for the "<?property::page>" syntax which gets more complicated with
 10+ * advanced nested variations "<?a::b::c::d::e>" or "<?a::b::<?c::<?d::e>>>".
 11+ *
 12+ * @since 0.1
 13+ *
 14+ * @file SemExExpressiveStringPieceSQ.php
 15+ * @ingroup SemanticExpressiveness
 16+ *
 17+ * @author Daniel Werner < danweetz@web.de >
 18+ */
 19+class SemExExpressiveStringPieceSQ extends SemExExpressiveStringPieceSQResult {
 20+
 21+ /* using:
 22+ * $origLimit = ini_set( 'pcre.recursion_limit', 8 );
 23+ * to enforce hard limit for nested syntax for this regex doesn't work. The whole regex will fail
 24+ */
 25+ protected static $regex = '<\?!?\s* [^<\|>]{1,64}? (?:\s*::\s*:?\s* (?>[^<>]{0,32}(?R)?){1,4})? \s*>';
 26+ protected static $regex_modifiers = 'x';
 27+ protected static $regex_essentials = array();
 28+
 29+
 30+ protected static function examineRegexMatch( array $backRefs, Parser $parser ) {
 31+ // handle one single short query of the whole sentence
 32+ // split it into its compontents:
 33+ preg_match(
 34+ '/^<(\?!|\?)\s* ([^<\|>)]+?) (?:\s*::\s* (:?) \s* (.*?) )? \s*>$/x',
 35+ $backRefs[0], $matches
 36+ );
 37+ $matches += array( 3 => false, 4 => false );
 38+ $isPlain = ( $matches[1] == '?!' );
 39+ $pageSrcExplicit = ( $matches[3] == ':' );
 40+
 41+ $property = SMWPropertyValue::makeUserProperty( $matches[2] );
 42+
 43+ $source = $matches[4];
 44+ if( $source === false ) {
 45+ $source = null; // source is current page
 46+ }
 47+ else {
 48+ // (recursivelly) examine the source for further short query syntax within:
 49+ $source = new SemExExpressiveString( $source, $parser, static::getType() );
 50+ $source = static::resolveDeepOneLinerNotation( $source );
 51+
 52+ if( $source === false ) {
 53+ // source is invalid in some way
 54+ return false;
 55+ }
 56+ }
 57+
 58+ // set the source of the query to a Title or another expressive string which
 59+ // can contain several short queries all over again
 60+ $query = new SemExShortQuery( $property, $source );
 61+ return new static(
 62+ new SemExShortQueryResult( $query, $parser )
 63+ );
 64+ }
 65+
 66+ /**
 67+ * Helper function to resolve short query notation like "<?a::b::c::d::e>".
 68+ * Note: "e" could also be another short query like "<?a::b::c::<?d::e>>", the parts before on
 69+ * the other hand are all properties which do not support a short query or expressive string
 70+ * source at the time.
 71+ *
 72+ * @param SemExExpressiveString $eSrc
 73+ * @return Title|SemExExpressiveString|false
 74+ */
 75+ protected static function resolveDeepOneLinerNotation( SemExExpressiveString $eSrc ) {
 76+ if( $eSrc->getPiece( 0 )->isExpressive() ) {
 77+ // whole meaning examined already and behind an expressive there can't be any "::" as
 78+ // separator between property and source unless we'd allow expressive property sources.
 79+ return $eSrc;
 80+ }
 81+
 82+ /*
 83+ * $eSrc only has one piece OR the next piece must be expressive. There could be further
 84+ * string pieces after the expressive one, but in that case they are part of the last part
 85+ */
 86+ $sources = preg_split(
 87+ '/\s*::\s*/',
 88+ $eSrc->getPiece( 0 )->getRawText()
 89+ );
 90+ $eSrc->removePieces( 0 );
 91+
 92+ // part behind last "::" is part of final source
 93+ $eSrc->addString( array_pop( $sources ), 0 );
 94+
 95+ if( ! $eSrc->hasExpressiveness() ) {
 96+ $eSrc = Title::newFromText( $eSrc->getRawText() );
 97+ if( $eSrc === null ) {
 98+ return false;
 99+ }
 100+ }
 101+
 102+ if( empty( $sources ) ) {
 103+ // no further "::" separations or expressiveness
 104+ return $eSrc;
 105+ }
 106+
 107+ $lastSrc = $eSrc;
 108+ $sources = array_reverse( $sources ); //last item first
 109+
 110+ foreach( $sources as $property ) {
 111+ $property = SMWPropertyValue::makeUserProperty( $property );
 112+ if( ! $property->isValid() ) {
 113+ return false;
 114+ }
 115+ $lastSrc = new SemExShortQuery( $property, $lastSrc );
 116+ }
 117+
 118+ return $lastSrc;
 119+ }
 120+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPieceSQ.php
___________________________________________________________________
Added: svn:eol-style
1121 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExPFParamsBasedFactory.php
@@ -0,0 +1,119 @@
 2+<?php
 3+
 4+/**
 5+ * Interface for classes offering a factory method for creating a new instance from parser function
 6+ * parameters.
 7+ *
 8+ * @since 0.1
 9+ *
 10+ * @file SemExPFParamsBasedFactory.php
 11+ * @ingroup SemanticExpressiveness
 12+ *
 13+ * @author Daniel Werner < danweetz@web.de >
 14+ */
 15+abstract class SemExPFParamsBasedFactory {
 16+
 17+ protected static $pfParamsValidatorElement;
 18+
 19+ /**
 20+ * Fabricates a new instance by a set of parser function parameters.
 21+ * If the given parameters were insufficient, false will be returned. Validation errors can be
 22+ * accessed by the $validator parameter.
 23+ *
 24+ * @param array $params raw parameters as given by a parser function
 25+ * @param array $defaultParams see Validator::setFunctionParams() $defaultParams parameter.
 26+ * @param null $validator
 27+ * @param bool $unknownInvalid
 28+ * @return __CLASS__|false
 29+ */
 30+ public static function newFromPFParams(
 31+ array $params,
 32+ array $defaultParams = array(),
 33+ &$validator = null,
 34+ $unknownInvalid = false
 35+ ) {
 36+ $params = static::getValidatedPFParams( $params, $defaultParams, $validator, $unknownInvalid, true );
 37+
 38+ if( $validator->hasFatalError() ) {
 39+ return false;
 40+ }
 41+ return static::newFromValidatedParams( $params, $validator );
 42+ }
 43+
 44+ /**
 45+ * Same as newFromPFParams() except that the $params array has to have the parameter names set
 46+ * as key values.
 47+ * If the given parameters were insufficient, false will be returned. Validation errors can be
 48+ * accessed by the $validator parameter.
 49+ *
 50+ * @param array $params raw parameters as values, parameter names as keys
 51+ * @param type $validator
 52+ * @param type $unknownInvalid
 53+ * @return __CLASS__
 54+ */
 55+ public static function newFromParamsArray(
 56+ array $params,
 57+ &$validator = null,
 58+ $unknownInvalid = false
 59+ ) {
 60+ $params = static::getValidatedPFParams( $params, array(), $validator, $unknownInvalid, false );
 61+
 62+ if( $validator->hasFatalError() ) {
 63+ return false;
 64+ }
 65+ return static::newFromValidatedParams( $params, $validator );
 66+ }
 67+
 68+ /**
 69+ * This should be overwritten by classes inheriting this one to fabricate a new instance by a set
 70+ * of parameters.
 71+ *
 72+ * @param array $params
 73+ * @return __CLASS__
 74+ */
 75+ public static function newFromValidatedParams( array $params ) {
 76+ return null;
 77+ }
 78+
 79+ /**
 80+ * Returns the validated parser function parameters by a given set of unprocessed parameters.
 81+ *
 82+ * @param array $params
 83+ * @param array $defaultParams see Validator::setFunctionParams() $defaultParams parameter.
 84+ * this has no effect if $pfStyle is set to false.
 85+ * @param null &$validator allows to get the Validator object used to validate the parameters.
 86+ * @param bool $unknownInvalid
 87+ * @param bool $pfParamsStyle if true this will not expect $params to have parameter keys as
 88+ * name, instead the names will be extracted from the values.
 89+ *
 90+ * @return array
 91+ */
 92+ public static function getValidatedPFParams(
 93+ array $params,
 94+ array $defaultParams = array(),
 95+ &$validator = null,
 96+ $unknownInvalid = false,
 97+ $pfParamsStyle = true
 98+ ) {
 99+ $validator = new Validator( static::$pfParamsValidatorElement, $unknownInvalid );
 100+
 101+ if( $pfParamsStyle ) {
 102+ $validator->setFunctionParams( $params, static::getPFParams(), $defaultParams );
 103+ } else {
 104+ $validator->setParameters( $params, static::getPFParams() );
 105+ }
 106+
 107+ $validator->validateParameters();
 108+
 109+ return $validator->getParameterValues();
 110+ }
 111+
 112+ /**
 113+ * Returns a description of all allowed function Parameters representing this class.
 114+ *
 115+ * @return array
 116+ */
 117+ public static function getPFParams() {
 118+ return array();
 119+ }
 120+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExPFParamsBasedFactory.php
___________________________________________________________________
Added: svn:eol-style
1121 + native
Index: trunk/extensions/SemanticExpressiveness/includes/validation/SemExParamManipulationQuerySource.php
@@ -0,0 +1,40 @@
 2+<?php
 3+
 4+/**
 5+* Parameter manipulation converting the value to a SMWStore listed within the global
 6+ * $smwgQuerySources config variable.
 7+ *
 8+ * @since 0.1
 9+ *
 10+ * @file SemExShortQueryResult.php
 11+ * @ingroup SemanticExpressiveness
 12+ * @ingroup ParameterManipulations
 13+ *
 14+ * @author Daniel Werner < danweetz@web.de >
 15+ */
 16+class SemExParamManipulationQuerySource extends ItemParameterManipulation {
 17+
 18+ /**
 19+ * Constructor.
 20+ *
 21+ * @since 0.4.14
 22+ */
 23+ public function __construct() {
 24+ parent::__construct();
 25+ }
 26+
 27+ /**
 28+ * @see ItemParameterManipulation::doManipulation
 29+ */
 30+ public function doManipulation( &$value, Parameter $parameter, array &$parameters ) {
 31+ global $smwgQuerySources;
 32+
 33+ // get specific store or take default:
 34+ if( array_key_exists( $value, $smwgQuerySources ) ) {
 35+ $value = new $smwgQuerySources[ $value ]();
 36+ } else {
 37+ $value = smwfGetStore(); // take default
 38+ }
 39+ }
 40+
 41+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/validation/SemExParamManipulationQuerySource.php
___________________________________________________________________
Added: svn:eol-style
142 + native
Index: trunk/extensions/SemanticExpressiveness/includes/validation/SemExCriterionIsProperty.php
@@ -0,0 +1,65 @@
 2+<?php
 3+
 4+/**
 5+ * Parameter criterion for 'Validator' stating that the value must be a SMW property.
 6+ * Optionally this will only allow properties of certain types.
 7+ *
 8+ * @since 0.1
 9+ *
 10+ * @file SemExShortQueryResult.php
 11+ * @ingroup SemanticExpressiveness
 12+ * @ingroup Criteria
 13+ *
 14+ * @author Daniel Werner < danweetz@web.de >
 15+ */
 16+class SemExCriterionIsProperty extends ItemParameterCriterion {
 17+
 18+ protected $allowedTypes;
 19+
 20+ /**
 21+ * Constructor.
 22+ *
 23+ * @param $allowedTypes string|string[] will only aprove of the property if its type id matches
 24+ * one of the given type ids. For example '_wpg' for properties of type page.
 25+ *
 26+ * @since 0.1
 27+ */
 28+ public function __construct( $allowedTypes = null ) {
 29+ if( $allowedTypes !== null && !is_array( $allowedTypes ) ) {
 30+ $allowedTypes = array( $allowedTypes );
 31+ }
 32+ $this->allowedTypes = $allowedTypes;
 33+ parent::__construct();
 34+ }
 35+
 36+ /**
 37+ * @see ItemParameterCriterion::validate
 38+ */
 39+ protected function doValidation( $value, Parameter $parameter, array $parameters ) {
 40+ // create SMW property from user input:
 41+ $prop = SMWPropertyValue::makeUserProperty( $value );
 42+
 43+ if( $this->allowedTypes !== null ) {
 44+ // filter unallowed types for this validation:
 45+ $type = $prop->getPropertyTypeID();
 46+ if( ! in_array( $type, $this->allowedTypes ) ) {
 47+ return false;
 48+ }
 49+ }
 50+ return $prop->isValid();
 51+ }
 52+
 53+ /**
 54+ * @see ItemParameterCriterion::getItemErrorMessage
 55+ */
 56+ protected function getItemErrorMessage( Parameter $parameter ) {
 57+ return '';
 58+ }
 59+
 60+ /**
 61+ * @see ItemParameterCriterion::getFullListErrorMessage
 62+ */
 63+ protected function getFullListErrorMessage( Parameter $parameter ) {
 64+ return '';
 65+ }
 66+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/validation/SemExCriterionIsProperty.php
___________________________________________________________________
Added: svn:eol-style
167 + native
Index: trunk/extensions/SemanticExpressiveness/includes/validation/SemExCriterionIsQuerySource.php
@@ -0,0 +1,47 @@
 2+<?php
 3+
 4+/**
 5+ * Parameter criterion for 'Validator' stating that the value must be the key of a registered
 6+ * SMWDataStore instance.
 7+ *
 8+ * @since 0.1
 9+ *
 10+ * @file SemExShortQueryResult.php
 11+ * @ingroup SemanticExpressiveness
 12+ * @ingroup Criteria
 13+ *
 14+ * @author Daniel Werner < danweetz@web.de >
 15+ */
 16+class SemExCriterionIsQuerySource extends ItemParameterCriterion {
 17+
 18+ /**
 19+ * Constructor.
 20+ *
 21+ * @since 0.1
 22+ */
 23+ public function __construct() {
 24+ parent::__construct();
 25+ }
 26+
 27+ /**
 28+ * @see ItemParameterCriterion::validate
 29+ */
 30+ protected function doValidation( $value, Parameter $parameter, array $parameters ) {
 31+ global $smwgQuerySources;
 32+ return array_key_exists( $value, $smwgQuerySources );
 33+ }
 34+
 35+ /**
 36+ * @see ItemParameterCriterion::getItemErrorMessage
 37+ */
 38+ protected function getItemErrorMessage( Parameter $parameter ) {
 39+ return '';
 40+ }
 41+
 42+ /**
 43+ * @see ItemParameterCriterion::getFullListErrorMessage
 44+ */
 45+ protected function getFullListErrorMessage( Parameter $parameter ) {
 46+ return '';
 47+ }
 48+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/validation/SemExCriterionIsQuerySource.php
___________________________________________________________________
Added: svn:eol-style
149 + native
Index: trunk/extensions/SemanticExpressiveness/includes/validation/SemExParamManipulationProperty.php
@@ -0,0 +1,32 @@
 2+<?php
 3+
 4+/**
 5+* Parameter manipulation converting the value to a SMWPropertyValue.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SemExShortQueryResult.php
 10+ * @ingroup SemanticExpressiveness
 11+ * @ingroup ParameterManipulations
 12+ *
 13+ * @author Daniel Werner < danweetz@web.de >
 14+ */
 15+class SemExParamManipulationProperty extends ItemParameterManipulation {
 16+
 17+ /**
 18+ * Constructor.
 19+ *
 20+ * @since 0.4.14
 21+ */
 22+ public function __construct() {
 23+ parent::__construct();
 24+ }
 25+
 26+ /**
 27+ * @see ItemParameterManipulation::doManipulation
 28+ */
 29+ public function doManipulation( &$value, Parameter $parameter, array &$parameters ) {
 30+ $value = SMWPropertyValue::makeUserProperty( $value );
 31+ }
 32+
 33+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/validation/SemExParamManipulationProperty.php
___________________________________________________________________
Added: svn:eol-style
134 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExShortQueryAbstractResult.php
@@ -0,0 +1,176 @@
 2+<?php
 3+
 4+/**
 5+ * Class representing the result of a 'Semantic Expressiveness' short query as abstract value.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SemExShortQueryAbstractResult.php
 10+ * @ingroup SemanticExpressiveness
 11+ *
 12+ * @author Daniel Werner < danweetz@web.de >
 13+ */
 14+class SemExShortQueryAbstractResult extends SemExShortQueryResult {
 15+
 16+ public function getAbstractResult() {
 17+ // this is the abstract result already
 18+ return $this;
 19+ }
 20+
 21+ /**
 22+ * Returns an abstract representation of the result which expresses what exactly the query is all
 23+ * about. Does some extra formatting for pretty wiki text compared to getAbstractRawText(). If all
 24+ * the short query classes and outer wrapping for the context popup functionality is needed, use
 25+ * getWikiText() instead.
 26+ *
 27+ * @param mixed $linked Allows one of
 28+ * SemExShortQueryOutputOptions::LINK_NONE
 29+ * SemExShortQueryOutputOptions::LINK_ALL
 30+ * SemExShortQueryOutputOptions::LINK_TOPIC
 31+ * @param bool $showErrors can be set to true to show errors. Off by default.
 32+ *
 33+ * @return string
 34+ */
 35+ public function getShortWikiText(
 36+ $linked = SemExShortQueryOutputOptions::LINK_ALL,
 37+ $showErrors = false
 38+ ) {
 39+ $parts = $this->getAbstractParts( false, $linked === SemExShortQueryOutputOptions::LINK_ALL );
 40+ $source = $parts['source'];
 41+ $fromRef = $parts['fromref'];
 42+ $property = $parts['property'];
 43+
 44+ $out =
 45+ '<b>&lt;</b>' .
 46+ $this->buildAbstractText( $property, $source, $fromRef ) .
 47+ '<b>&gt;</b>';
 48+
 49+ $out = "<span class=\"abstractShortQueryValue\">$out</span>";
 50+
 51+ if( $linked === SemExShortQueryOutputOptions::LINK_TOPIC ) {
 52+ // wrap whole result in one link to the source
 53+ $topic = $this->getSource();
 54+ $out = "[[:{$topic}|{$out}]]";
 55+ }
 56+
 57+ if( $showErrors ) {
 58+ // don't get any error about the queries general success, just about invalid input
 59+ $out .= $this->getErrorTextForFormattedSQ();
 60+ }
 61+
 62+ return $out;
 63+ }
 64+
 65+ public function getWikiText(
 66+ $linked = SemExShortQueryOutputOptions::LINK_ALL,
 67+ $showErrors = true
 68+ ) {
 69+ return $this->getWikiText_internal( $linked, $showErrors, true );
 70+ }
 71+
 72+ /**
 73+ * Returns an abstract representation of the result which expresses what exactly the query is all
 74+ * about.
 75+ *
 76+ * @return string
 77+ */
 78+ public function getRawText() {
 79+ $parts = $this->getAbstractParts( true, false );
 80+ $text = $this->buildAbstractText(
 81+ $parts['property'],
 82+ $parts['source'],
 83+ $parts['fromref']
 84+ );
 85+ return "<$text>";
 86+ }
 87+
 88+ /**
 89+ * Helper function to put together the abstract string
 90+ */
 91+ protected function buildAbstractText( $property, $source, $fromRef = false ) {
 92+ if( $source === null ) {
 93+ // query from current page
 94+ // don't display any further info
 95+ $ret = $property;
 96+ } elseif( $fromRef ) {
 97+ // query 'from ref'
 98+ $ret = wfMsgForContent( 'semex-shortquery-title-from-ref', $property, $source );
 99+ } else {
 100+ // query from any other known page or expressive string
 101+ $ret = wfMsgForContent( 'semex-shortquery-title', $property, $source );
 102+ }
 103+ return $ret;
 104+ }
 105+
 106+ /**
 107+ * Returns all necessary information part of abstract information about the query.
 108+ *
 109+ * @param bool $raw
 110+ * @param bool $linked
 111+ *
 112+ * @return string[] with keys 'property', 'fromref' and 'source'
 113+ */
 114+ protected function getAbstractParts( $raw, $linked ) {
 115+ $parts = array();
 116+ $parts['fromref'] = false;
 117+
 118+ $property = $this->query->getProperty()->getDataItem()->getLabel();
 119+ if( $linked ) {
 120+ $propTitle = Title::makeTitle( SMW_NS_PROPERTY, $property );
 121+ $property = "[[:{$propTitle->getPrefixedText()}|$property]]";
 122+ }
 123+ if( ! $raw ) {
 124+ $property = "<span class=\"property\">$property</span>";
 125+ }
 126+ $parts['property'] = $property;
 127+
 128+ if(
 129+ $this->getSource() !== null
 130+ && $this->parser->getTitle()->getPrefixedText() === $this->getSource()->getPrefixedText()
 131+ ) {
 132+ // query from current page
 133+ $parts['source'] = null;
 134+ }
 135+ elseif( $this->query->getSourceType() === SemExShortQuery::SOURCE_FROM_REF ) {
 136+ // query 'from ref'
 137+ $parts['fromref'] = true;
 138+ $parts['source'] = $this->query->getSource()->getDataItem()->getLabel();
 139+ if( ! $raw ) {
 140+ $parts['source'] = "<u>{$parts['source']}</u>";
 141+ }
 142+ }
 143+ else {
 144+ if( $this->getSource() === null ) {
 145+ if( $this->sourceResult !== null ) {
 146+ // source from SemExShortQuery object. Put it into an expressive string so we can get
 147+ // the expressive representation without troubles
 148+ $source = new SemExExpressiveString( '', $this->parser, SEMEX_EXPR_PIECE_SQRESULT );
 149+ $source->addPieces( new SemExExpressiveStringPieceSQResult(
 150+ $this->sourceResult // take cached version so we don't have to query again
 151+ ) );
 152+ }
 153+ else {
 154+ // source must be from unresolved expressive string
 155+ $source = $this->query->getSource();
 156+ }
 157+
 158+ $source = ( $raw )
 159+ ? $source->getRawText( true )
 160+ : $source->getWikiText( true, $linked );
 161+ }
 162+ else {
 163+ // query from any other known page
 164+ $source = $this->getSource()->getPrefixedText();
 165+ if( $linked ) {
 166+ $source = "[[:$source]]";
 167+ }
 168+ }
 169+ $parts['source'] = $source;
 170+ }
 171+ if( $parts['source'] !== null && ! $raw ) {
 172+ $parts['source'] = "<span class=\"source\">{$parts['source']}</span>";
 173+ }
 174+
 175+ return $parts;
 176+ }
 177+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExShortQueryAbstractResult.php
___________________________________________________________________
Added: svn:eol-style
1178 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPF.php
@@ -0,0 +1,132 @@
 2+<?php
 3+
 4+/**
 5+ * Class for the '?to?!' parser function, basically a limited converter for expressive strings.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SemExExpressiveStringPF.php
 10+ * @ingroup SemanticExpressiveness
 11+ *
 12+ * @author Daniel Werner < danweetz@web.de >
 13+ */
 14+class SemExExpressiveStringPF extends ParserHook {
 15+
 16+ public function __construct() {
 17+ // make this a parser function extension (no tag extension) only:
 18+ parent::__construct( false, true, ParserHook::FH_NO_HASH );
 19+ }
 20+
 21+ /**
 22+ * No LSB in pre-5.3 PHP, to be refactored later
 23+ */
 24+ public static function staticInit( Parser &$parser ) {
 25+ $instance = new self;
 26+ $instance->init( $parser );
 27+ return true;
 28+ }
 29+
 30+ /**
 31+ * Gets the name of the parser hook.
 32+ * @see ParserHook::getName
 33+ *
 34+ * @return string
 35+ */
 36+ protected function getName() {
 37+ return '?to?!';
 38+ }
 39+
 40+ /**
 41+ * Returns an array containing the parameter info.
 42+ * @see ParserHook::getParameterInfo
 43+ *
 44+ * @return array
 45+ */
 46+ protected function getParameterInfo( $type ) {
 47+ $params = array();
 48+
 49+ # input text.
 50+ # since 0.1
 51+ $params['text'] = new Parameter( 'text' );
 52+
 53+ $pieceTypesCriteria = new CriterionInArray(
 54+ array_values( SemExExpressiveString::getRegisteredPieceTypeNames() )
 55+ );
 56+
 57+ $params['detect'] = new ListParameter( 'detect' );
 58+ $params['detect']->addCriteria( $pieceTypesCriteria );
 59+ $params['detect']->setDefault( false, false );
 60+
 61+ $params['ignore'] = new ListParameter( 'ignore' );
 62+ $params['ignore']->addCriteria( $pieceTypesCriteria );
 63+ $params['ignore']->setDefault( array(), false );
 64+
 65+ $params = array_merge( $params, SemExExpressiveStringOutputOptions::getPFParams() );
 66+
 67+ return $params;
 68+ }
 69+
 70+ /**
 71+ * Returns the list of default parameters.
 72+ * @see ParserHook::getDefaultParameters
 73+ *
 74+ * @return array
 75+ */
 76+ protected function getDefaultParameters( $type ) {
 77+ return array(
 78+ array( 'text', Validator::PARAM_UNNAMED ),
 79+ );
 80+ }
 81+
 82+ /**
 83+ * Returns the parser function options.
 84+ * @see ParserHook::getFunctionOptions
 85+ *
 86+ * @return array
 87+ */
 88+ protected function getFunctionOptions() {
 89+ return array(
 90+ 'noparse' => true,
 91+ 'isHTML' => false
 92+ );
 93+ }
 94+
 95+ /**
 96+ * Renders and returns the output.
 97+ * @see ParserHook::renderTag
 98+ *
 99+ * @param array $parameters
 100+ * @return string
 101+ */
 102+ public function render( array $parameters ) {
 103+ // get all types that should be handled by this
 104+ $enabledTypes = array();
 105+
 106+ if( $parameters['detect'] !== false ) {
 107+ foreach( $parameters['detect'] as $typeName ) {
 108+ $type = SemExExpressiveString::getRegisteredPieceTypeByName( $typeName );
 109+ if( $type !== null ) {
 110+ $enabledTypes[] = $type;
 111+ }
 112+ }
 113+ } elseif( empty( $parameters['ignore'] ) ) {
 114+ $enabledTypes = null; // same as next but constructor will process this faster
 115+ } else {
 116+ $enabledTypes = SemExExpressiveString::getRegisteredPieceTypeNames();
 117+ }
 118+
 119+ $enabledTypes = array_flip( $enabledTypes );
 120+ foreach( $parameters['ignore'] as $typeName ) {
 121+ unset( $enabledTypes[ SemExExpressiveString::getRegisteredPieceTypeByName( $typeName ) ] );
 122+ }
 123+ $enabledTypes = array_flip( $enabledTypes );
 124+
 125+ // build expressive string from input with enabled types:
 126+ $exprString = new SemExExpressiveString( $parameters['text'], $this->parser, $enabledTypes );
 127+
 128+ /** @ToDo: Make it possible to define options per piece type per parameter prefixes */
 129+ $options = SemExExpressiveStringOutputOptions::newFromValidatedParams( $parameters );
 130+ return $exprString->getOutput( $options );
 131+ }
 132+
 133+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPF.php
___________________________________________________________________
Added: svn:eol-style
1134 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPieceByRegex.php
@@ -0,0 +1,118 @@
 2+<?php
 3+
 4+/**
 5+ * Abstract class representing one piece of a SemExExpressiveString with abstract features to
 6+ * initialize pieces of a type by a matching regular expression.
 7+ *
 8+ * @since 0.1
 9+ *
 10+ * @file SemExExpressiveStringPiece.php
 11+ * @ingroup SemanticExpressiveness
 12+ *
 13+ * @author Daniel Werner < danweetz@web.de >
 14+ */
 15+abstract class SemExExpressiveStringPieceByRegex extends SemExExpressiveStringPiece {
 16+
 17+ /**
 18+ * The regular expression to match pieces which will be considered candidates for being pieces of
 19+ * this type and which can be further examined in static::examineRegexMatch()
 20+ * This is only the inner regex, modifiers can be set via static::$regex_modifiers
 21+ * The '/' character has to be escaped '\/' within the expression.
 22+ * @var string
 23+ */
 24+ protected static $regex;
 25+
 26+ /**
 27+ * Optional modifiers for the static::$regex regex.
 28+ * @var string
 29+ */
 30+ protected static $regex_modifiers = '';
 31+
 32+ /**
 33+ * Array telling which backreferences of $regex are essential information and which can be ignored.
 34+ * The array index refers to the backreference index within $regex, if it is set to true it means
 35+ * that the value will be made available within static::examineRegexMatch().
 36+ * The whole matched string will be made available anyway, so it might not be necessary to request
 37+ * further backrefs here.
 38+ * @var bool[]
 39+ */
 40+ protected static $regex_essentials = array();
 41+
 42+
 43+ protected static function examineString( $string, Parser $parser ) {
 44+ // the regex is built to hold the whole matched string as backref for later
 45+ $regex = '/(' . static::$regex . ')/' . static::$regex_modifiers;
 46+ $rawParts = preg_split( $regex, $string, -1, PREG_SPLIT_DELIM_CAPTURE );
 47+
 48+ $count = count( $rawParts ) ;
 49+ if( $count <= 1 ) {
 50+ // no match for this type
 51+ return false;
 52+ }
 53+
 54+ $parts = array();
 55+ $backrefs = count( static::$regex_essentials );
 56+
 57+ // group backrefs and actual match which belong together, put non-expressive strings inbetween
 58+ // so we have an array full of strings and sub-arrays still in the right order:
 59+ for( $i = 0; $i < $count; $i++ ){
 60+ $parts[] = $rawParts[ $i ]; // string or empty part inbetween
 61+ $i++;
 62+ if( $i === $count ) {
 63+ break; // last piece
 64+ }
 65+
 66+ // get all essential backrefs for the matching piece:
 67+ $essentialBackrefs = array(
 68+ $rawParts[ $i ] // the part holding the whole matched string, the raw piece
 69+ );
 70+ for( $k = 0; $k < $backrefs; $k++ ) {
 71+ $i++;
 72+ if( static::$regex_essentials[ $k ] ) {
 73+ $essentialBackrefs[] = $rawParts[ $i ];
 74+ }
 75+ }
 76+ $parts[] = $essentialBackrefs;
 77+ }
 78+
 79+ // walk through the created array and call sub-function for each array element which holds all the
 80+ // information about one potential match for a piece of this type:
 81+ $result = array();
 82+ $i = -1;
 83+ foreach( $parts as $part ) {
 84+ $i++;
 85+ if( is_string( $part ) ) {
 86+ // only each second element can be a regex match
 87+ if( $part !== '' ) {
 88+ $result[] = new SemExExpressiveStringPiece( $part );
 89+ }
 90+ continue;
 91+ }
 92+
 93+ $piece = static::examineRegexMatch( $part, $parser );
 94+
 95+ if( $piece === false ) {
 96+ // not a piece of this type, consider it a meaningless string
 97+ $piece = new SemExExpressiveStringPiece( $part[0], $parser );
 98+ }
 99+
 100+ $result[] = $piece;
 101+ }
 102+
 103+ return $result;
 104+ }
 105+
 106+ /**
 107+ * Function called by examineString() when a static::$regex matching string has been found.
 108+ * Returns the resolved piece or false in case this is not a piece of this type.
 109+ *
 110+ * @param string[] $backRefs all references from static::$regex which are marked as essential
 111+ * by static::$regex_essentials. The index 0 contains the whole match.
 112+ * @param Parser $parser
 113+ *
 114+ * @return SemExExpressiveStringPiece|false
 115+ */
 116+ protected static function examineRegexMatch( array $backRefs, Parser $parser ) {
 117+ return false;
 118+ }
 119+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringPieceByRegex.php
___________________________________________________________________
Added: svn:eol-style
1120 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringOutputOptions.php
@@ -0,0 +1,305 @@
 2+<?php
 3+
 4+/**
 5+ * Class for defining options for expressive strings output.
 6+ * SemExExpressiveString::getOutput() can be used to get the formatted output in the form defined by
 7+ * a SemExExpressiveStringOutputOptions object.
 8+ *
 9+ * @since 0.1
 10+ *
 11+ * @file SemExExpressiveStringOutputOptions.php
 12+ * @ingroup SemanticExpressiveness
 13+ *
 14+ * @author Daniel Werner < danweetz@web.de >
 15+ */
 16+class SemExExpressiveStringOutputOptions extends SemExPFParamsBasedFactory {
 17+
 18+ protected static $pfParamsValidatorElement = 'expressive string output options';
 19+
 20+ /**
 21+ * With this format output will be printed as suitable MediaWiki wikitext markup.
 22+ */
 23+ const FORMAT_WIKITEXT = 1;
 24+ /**
 25+ * If this is set as format, all links, errors and markup of any kind will not be printed even
 26+ * though the other options are set accordingly.
 27+ */
 28+ const FORMAT_RAW = 2;
 29+ /*
 30+ * @todo: HTML support not yet implemented in any output printer, include this if it should ever
 31+ * be required.
 32+ */
 33+ //const FORMAT_HTML = 3;
 34+
 35+
 36+ /**
 37+ * Implies that there will be no links at all within the output.
 38+ */
 39+ const LINK_NONE = false;
 40+
 41+ /**
 42+ * Implies that links will be printed within the output.
 43+ */
 44+ const LINK_ALL = true;
 45+
 46+
 47+ /**
 48+ * The output will be in its abstract representation if a failure occured.
 49+ */
 50+ const ABSTRACT_IF_FAILURE = true;
 51+
 52+ /**
 53+ * The output will never have an abstract representation, even if a failure has occured. Normally
 54+ * an empty string will be returned instead.
 55+ */
 56+ const NO_ABSTRACT = false;
 57+
 58+ /**
 59+ * This can be used to enforce abstract output.
 60+ */
 61+ const ABSTRACT_ONLY = 2;
 62+
 63+
 64+ protected $link = self::LINK_ALL;
 65+ protected $showInfo = true;
 66+ protected $showAbstract = null;
 67+ protected $showErrors = null;
 68+ protected $format = self::FORMAT_WIKITEXT;
 69+
 70+ /**
 71+ * Merges options of another SemExExpressiveStringOutputOptions object with this objects options.
 72+ *
 73+ * @note This is only save when merging the object with an ancestor or equal instance but should
 74+ * not be done with objects of a descendant option class.
 75+ *
 76+ * @param SemExExpressiveStringOutputOptions $options
 77+ */
 78+ public function mergeOptions( SemExExpressiveStringOutputOptions $options ) {
 79+ $options = get_object_vars( $options );
 80+ foreach( $options as $var => $val ) {
 81+ $this->{ $var } = $val;
 82+ }
 83+ }
 84+
 85+ /**
 86+ * Defines whether the output should contain links. The following values are possible:
 87+ *
 88+ * self::LINK_NONE - No links at all.
 89+ * self::LINK_ALL - Links will be used where possible.
 90+ *
 91+ * null - Now the option depends on getShowInfo(). If it is true, then this will behave if as
 92+ * self::LINK_ALL were set, otherwise it will be self::LINK_NONE.
 93+ *
 94+ * @param mixed $val
 95+ * @return string previous value
 96+ */
 97+ public function setLink( $val ) {
 98+ return wfSetVar( $this->link, $val );
 99+ }
 100+
 101+ /**
 102+ * Defines whether the expressive piece should be formatted as such and display all the
 103+ * available abstract information in case it fails.
 104+ * This is sort of a group-option setting default behavior for various other options which
 105+ * consider this option as their default but also can overwrite this explicitly.
 106+ *
 107+ * @param bool $val
 108+ * @return bool previous value
 109+ */
 110+ public function setShowInfo( $val ) {
 111+ return wfSetVar( $this->showInfo, $val );
 112+ }
 113+
 114+ /**
 115+ * Defines whether the abstract representation should be displayed if an error occurs or if
 116+ * perhaps only the abstract value should be returned. The following four options are allowed:
 117+ *
 118+ * self::ABSTRACT_IF_FAILURE - The abstract value will be displayed if an error occurs.
 119+ * self::NO_ABSTRACT - Abstract value will never be displayed, even on failure.
 120+ * self::ABSTRACT_ONLY - Only the abstract value will be returned.
 121+ *
 122+ * null - Now the option depends on getShowInfo(). If it is true, then this will behave as if
 123+ * self::ABSTRACT_IF_FAILURE were set, otherwise it will be self::NO_ABSTRACT.
 124+ *
 125+ * @param mixed|null $val
 126+ * @return mixed|null previous value
 127+ */
 128+ public function setShowAbstract( $val ) {
 129+ return wfSetVar( $this->showAbstract, $val );
 130+ }
 131+
 132+ /**
 133+ * Defines whether the output should reveal any eventual errors as messages. By default and if
 134+ * null is set, the behavior will depend on and equal getShowInfo().
 135+ *
 136+ * @param bool|null $val
 137+ * @return bool|null previous value
 138+ */
 139+ public function setShowErrors( $val ) {
 140+ return wfSetVar( $this->showErrors, $val );
 141+ }
 142+
 143+ /**
 144+ * Defines the output format.
 145+ *
 146+ * @param integer $val Allows to set one of the follwoing output formats:
 147+ *
 148+ * self::FORMAT_WIKITEXT - The output will be returned as wikitext (default)
 149+ * self::FORMAT_HTML - The output will be formatted and properly escaped to be used
 150+ * directly in HTML (not implemented yet!)
 151+ *
 152+ * @return integer previous value
 153+ */
 154+ public function setFormat( $val ) {
 155+ return wfSetVar( $this->format, $val );
 156+ }
 157+
 158+ public function getShowInfo() { return $this->showInfo; }
 159+ public function getFormat() { return $this->format; }
 160+
 161+ /**
 162+ * Returns whether links should be generated. By default this equals getShowInfo().
 163+ *
 164+ * @return mixed previous value
 165+ */
 166+ public function getLink() {
 167+ if( $this->link !== null ) {
 168+ return $this->link;
 169+ }
 170+ // by default show links when displaying infos
 171+ return $this->showInfo;
 172+ }
 173+
 174+ /**
 175+ * Returns whether the abstract representation should be displayed if the query goes wrong or
 176+ * if perhaps only the abstract value should be returned without querying at all.
 177+ * By default this depends on and equals the value of getShowInfo()
 178+ *
 179+ * @return mixed
 180+ */
 181+ public function getShowAbstract() {
 182+ if( $this->showErrors !== null ) {
 183+ return $this->showErrors;
 184+ }
 185+ // by default show abstract when displaying infos
 186+ return $this->showInfo;
 187+ }
 188+
 189+ /**
 190+ * Returns whether Errors should be displayed for the output.
 191+ * By default this depends on and equals the value of getShowInfo()
 192+ *
 193+ * @return bool
 194+ */
 195+ public function getShowErrors() {
 196+ if( $this->showErrors !== null ) {
 197+ return $this->showErrors;
 198+ }
 199+ // by default show errors when displaying infos
 200+ return $this->showInfo;
 201+ }
 202+
 203+
 204+ /**
 205+ * @see SemExPFParamsBasedFactory::newFromValidatedParams()
 206+ */
 207+ public static function newFromValidatedParams( array $params ) {
 208+ $sqOpt = new static();
 209+
 210+ $format = $params['format'];
 211+ switch( $format ) {
 212+ case 'raw':
 213+ $format = self::FORMAT_RAW;
 214+ break;
 215+ case 'wiki':
 216+ default:
 217+ $format = self::FORMAT_WIKITEXT;
 218+ break;
 219+ }
 220+
 221+ $link = $params['link'];
 222+ switch( $link ) {
 223+ case 'all':
 224+ case 'show':
 225+ case 'subject':
 226+ $link = self::LINK_ALL;
 227+ break;
 228+ case 'none':
 229+ $link = self::LINK_NONE;
 230+ break;
 231+ case 'auto':
 232+ default:
 233+ // links only when displaying info
 234+ $link = null;
 235+ }
 236+
 237+ $abstract = $params['abstract'];
 238+ switch( $abstract ) {
 239+ case 'show':
 240+ $abstract = self::ABSTRACT_IF_FAILURE;
 241+ break;
 242+ case 'hide':
 243+ $abstract = self::NO_ABSTRACT;
 244+ break;
 245+ case 'only':
 246+ $abstract = self::ABSTRACT_ONLY;
 247+ break;
 248+ case 'auto':
 249+ default:
 250+ // abstract info only when displaying info
 251+ $abstract = null;
 252+ }
 253+
 254+ $errors = $params['errors'];
 255+ switch( $errors ) {
 256+ case 'show':
 257+ $errors = true;
 258+ break;
 259+ case 'hide':
 260+ $errors = false;
 261+ break;
 262+ case 'auto':
 263+ default:
 264+ // show errors only when displaying info
 265+ $errors = null;
 266+ }
 267+
 268+ $sqOpt->setFormat( $format );
 269+ $sqOpt->setLink( $link );
 270+ $sqOpt->setShowInfo( $params['info'] );
 271+ $sqOpt->setShowAbstract( $abstract );
 272+ $sqOpt->setShowErrors( $errors );
 273+
 274+ return $sqOpt;
 275+ }
 276+
 277+ /**
 278+ * Returns a description of all allowed function Parameters representing SemExShortQueryResultOptions.
 279+ *
 280+ * @return array
 281+ */
 282+ public static function getPFParams() {
 283+ $params = array();
 284+
 285+ $params['format'] = new Parameter( 'format' );
 286+ $params['format']->addCriteria( new CriterionInArray( 'wiki', 'raw' ) );
 287+ $params['format']->setDefault( 'wiki' );
 288+
 289+ $params['info'] = new Parameter( 'info', Parameter::TYPE_BOOLEAN );
 290+ $params['info']->setDefault( true );
 291+
 292+ $params['link'] = new Parameter( 'link' );
 293+ $params['link']->addCriteria( new CriterionInArray( 'all', 'show', 'subject', 'none', 'auto' ) );
 294+ $params['link']->setDefault( 'auto' );
 295+
 296+ $params['abstract'] = new Parameter( 'abstract' );
 297+ $params['abstract']->addCriteria( new CriterionInArray( 'only', 'show', 'hide', 'auto' ) );
 298+ $params['abstract']->setDefault( 'auto' );
 299+
 300+ $params['errors'] = new Parameter( 'errors' );
 301+ $params['errors']->addCriteria( new CriterionInArray( 'show', 'hide', 'auto' ) );
 302+ $params['errors']->setDefault( 'auto' );
 303+
 304+ return $params;
 305+ }
 306+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveStringOutputOptions.php
___________________________________________________________________
Added: svn:eol-style
1307 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExShortQueryOutputOptions.php
@@ -0,0 +1,92 @@
 2+<?php
 3+
 4+/**
 5+ * Class for defining options for a 'Semantic Expressiveness' short query.
 6+ * SemExShortQueryProcessor::getResultFromQuery() can be used to get a short queries result using
 7+ * a SemExShortQuery and these options.
 8+ * SemExShortQueryResult::getOutput() can also be used to get the formatted output specified by a
 9+ * SemExShortQuery object.
 10+ *
 11+ * @since 0.1
 12+ *
 13+ * @file SemExShortQueryResultOptions.php
 14+ * @ingroup SemanticExpressiveness
 15+ *
 16+ * @author Daniel Werner < danweetz@web.de >
 17+ */
 18+class SemExShortQueryOutputOptions extends SemExExpressiveStringOutputOptions {
 19+
 20+ protected static $pfParamsValidatorElement = 'short query output options';
 21+
 22+ /**
 23+ * Link depending on the properties Type. Values coming from properties of Type 'Page' will
 24+ * display a link. If the queried value consists of multiple values or is a set of data
 25+ * bundled in one property, the linking will happen individually for each part if appropriate.
 26+ */
 27+ const LINK_ALL = true;
 28+
 29+ /**
 30+ * The output will be wrapped inside a link to the queries source page, even if the property
 31+ * value is a value of type 'Page' which would bring its own link to another page. This makes
 32+ * sense for properties which are not of type 'Page' but kind of represent the whole article,
 33+ * e.g. a 'Name' property.
 34+ */
 35+ const LINK_TOPIC = 2;
 36+
 37+
 38+ /**
 39+ * Defines whether the short query result should contain a link to the queried property
 40+ * or the target page. Following values are possible:
 41+ *
 42+ * self::LINK_NONE - No links at all.
 43+ * self::LINK_ALL - Link depending on the properties Type. Type 'Page' will display link.
 44+ * self::LINK_TOPIC - The property value will be wrapped inside a link to the source page,
 45+ * even if the property value is a value of type 'Page' which would
 46+ * bring its own link to another page.
 47+ *
 48+ * null - Now the option depends on getShowInfo(). If it is true, then this will behave if as
 49+ * self::LINK_ALL were set, otherwise it will be self::LINK_NONE.
 50+ *
 51+ * @param mixed $val
 52+ * @return string previous value
 53+ */
 54+ public function setLink( $val ) {
 55+ return parent::setLink( $val );
 56+ }
 57+
 58+ /**
 59+ * @see SemExPFParamsBasedFactory::newFromValidatedParams()
 60+ */
 61+ public static function newFromValidatedParams( array $params ) {
 62+ $sqOpt = parent::newFromValidatedParams( $params );
 63+
 64+ $link = $params['link'];
 65+ if( $link == 'topic' || $link == 'source' ) {
 66+ $sqOpt->setLink( self::LINK_TOPIC );
 67+ }
 68+
 69+ return $sqOpt;
 70+ }
 71+
 72+ /**
 73+ * @see SemExExpressiveStringOutputOptions::getPFParams()
 74+ *
 75+ * @return array
 76+ */
 77+ public static function getPFParams() {
 78+ $params = parent::getPFParams();
 79+
 80+ // add 'topic' to the allowed 'link' parameter values:
 81+ $linkCriteria = $params['link']->getCriteria();
 82+ $linkCriteria = array_merge( $linkCriteria[0]->getAllowedValues(), array( 'topic', 'source' ) );
 83+
 84+ $newLink = new Parameter( 'link' );
 85+ $newLink->addCriteria( new CriterionInArray( $linkCriteria ) );
 86+ $newLink->setDefault( $params['link']->getDefault() );
 87+
 88+ // overwrite old parameter definition:
 89+ $params['link'] = $newLink;
 90+
 91+ return $params;
 92+ }
 93+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExShortQueryOutputOptions.php
___________________________________________________________________
Added: svn:eol-style
194 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveString.php
@@ -0,0 +1,507 @@
 2+<?php
 3+
 4+/**
 5+ * Class which can process a string which potentially contains one or several SemExShortQueryResult
 6+ * representations. Once initialized, this will offer access to all failed and successful short query
 7+ * results and text parts inbetween. Also allows to convert the whole string into plain text or to
 8+ * convert containing
 9+ *
 10+ * @since 0.1
 11+ *
 12+ * @file SemExExpressiveString.php
 13+ * @ingroup SemanticExpressiveness
 14+ *
 15+ * @author Daniel Werner < danweetz@web.de >
 16+ */
 17+class SemExExpressiveString {
 18+
 19+ protected $enabledPieceTypes;
 20+ protected $parser;
 21+
 22+ /**
 23+ * All parts the original string $string consists of
 24+ * @var array of SemExShortQueryResult objects and/or strings
 25+ */
 26+ protected $pieces = array();
 27+
 28+ /**
 29+ * Constructor
 30+ *
 31+ * @param string $string
 32+ * @param Parser $parser
 33+ * @param array|string $enabledPieceTypes allows to define which expressive types should be
 34+ * detected. See static::getRegisteredPieceTypes() for all possible types.
 35+ */
 36+ function __construct( $string, Parser $parser, $enabledPieceTypes = null ) {
 37+ if( $enabledPieceTypes === null ) {
 38+ $enabledPieceTypes = static::getRegisteredPieceTypes();
 39+ }
 40+ elseif( ! is_array( $enabledPieceTypes ) ) {
 41+ // only one type, don't care about priority
 42+ $enabledPieceTypes = array( $enabledPieceTypes );
 43+ }
 44+ else {
 45+ // make sure we get the priority as key in user-given array
 46+ $enabledPieceTypes = $this->injectPieceTypePriorities( $enabledPieceTypes );
 47+ }
 48+ krsort( $enabledPieceTypes ); // highest will be initialized last
 49+ $this->enabledPieceTypes = $enabledPieceTypes;
 50+ $this->parser = $parser;
 51+
 52+ // add string as non-expressive string...
 53+ $this->addString( $string );
 54+
 55+ // ... and examine its expressive meaning one by one:
 56+ foreach( $this->getEnabledPieceTypes() as $pieceType ) {
 57+ $pieceType :: initWithin( $this );
 58+ }
 59+ }
 60+
 61+ /**
 62+ * Returns all parts the original string consists of.
 63+ *
 64+ * @return SemExExpressiveStringPiece[]
 65+ */
 66+ public function getPieces() {
 67+ return $this->pieces;
 68+ }
 69+
 70+ /**
 71+ * Returns a piece from a given index or null if the index doesn't exist.
 72+ *
 73+ * @param int $index
 74+ * @return SemExExpressiveStringPiece
 75+ */
 76+ public function getPiece( $index ) {
 77+ if( ! array_key_exists( $index, $this->pieces ) ) {
 78+ return null;
 79+ }
 80+ return $this->pieces[ $index ];
 81+ }
 82+
 83+ /**
 84+ * Returns all pieces of the string which which have their own expressive meaning and not just
 85+ * represent a simple string.
 86+ *
 87+ * @return SemExExpressiveStringPiece[]
 88+ */
 89+ public function getExpressivePieces() {
 90+ $exprPieces = array();
 91+ foreach( $this->pieces as $piece ) {
 92+ if( $piece->isExpressive() ) {
 93+ $exprPieces[] = $piece;
 94+ }
 95+ }
 96+ return $exprPieces;
 97+ }
 98+
 99+ /**
 100+ * Returns whether the string has any expressive pieces.
 101+ *
 102+ * @return bool
 103+ */
 104+ public function hasExpressiveness() {
 105+ foreach( $this->pieces as $piece ) {
 106+ if( $piece->isExpressive() ) {
 107+ return true;
 108+ }
 109+ }
 110+ return false;
 111+ }
 112+
 113+ /**
 114+ * Returns true if any expressive piece is not resolvable, meaning the piece doesn't have a pure
 115+ * textual representation.
 116+ *
 117+ * @return bool
 118+ */
 119+ public function hasUnresolvablePiece() {
 120+ foreach( $this->pieces as $piece ) {
 121+ if( $piece->isUnresolvable() ) {
 122+ return true;
 123+ }
 124+ }
 125+ return false;
 126+ }
 127+
 128+ /**
 129+ * This will examine a string for its expressive meaning and add all parts accordingly.
 130+ *
 131+ * @param string $string
 132+ * @param int $index see self::addPieces()
 133+ */
 134+ public function addExpressiveString( $string, $index = null ) {
 135+ $newExprString = new static( $string, $this->parser, $this->getEnabledPieceTypes() );
 136+ $this->addPieces( $newExprString->getPieces(), $index );
 137+ }
 138+
 139+ /**
 140+ * Shorthand function for self::addPieces( new SemExExpressiveStringPiece( $stringPiece ) ).
 141+ *
 142+ * @param string $stringPiece
 143+ * @param int $index see self::addPieces()
 144+ */
 145+ public function addString( $stringPiece, $index = null ) {
 146+ $piece = new SemExExpressiveStringPiece( $stringPiece );
 147+ $this->addPieces( array( $piece ), $index );
 148+ }
 149+
 150+ /**
 151+ * Allows to insert additional pieces to the expressive string. By default at the end
 152+ * or optionally at a certain index.
 153+ *
 154+ * @param SemExExpressiveStringPiece|SemExExpressiveStringPiece[] $pieces
 155+ * @param int $index if this is set, the new pieces will be inserted at this index,
 156+ * the original item at this position will be moved behind the inserted ones.
 157+ * Negative index will insert the items that far from the end.
 158+ */
 159+ public function addPieces( $pieces, $index = null ) {
 160+ if( ! is_array( $pieces ) ) {
 161+ $pieces = array( $pieces );
 162+ }
 163+ $this->pieces = array_values( $this->pieces ); // re-numerate to be on the safe side
 164+ $totalPieces = count( $this->pieces );
 165+
 166+ if( $index < 0 ) {
 167+ // -1 will insert $pieces before last current piece
 168+ $index = $totalPieces - $index;
 169+ if( $index < 0 ) {
 170+ $index = 0;
 171+ }
 172+ }
 173+
 174+ if( $index === null || $index >= $totalPieces ) {
 175+ // pieces will be added at the end
 176+ $index = $totalPieces;
 177+ }
 178+ else {
 179+ // pieces will be inserted before an existing one
 180+ // add the piece after new pieces for reduction
 181+ $pieces[] = $this->pieces[ $index ];
 182+ unset( $this->pieces[ $index ] );
 183+ }
 184+
 185+ if( $index > 0 && $totalPieces > 0 ) {
 186+ // add the one before new pieces for reduction
 187+ $index--;
 188+ $pieces = array_merge(
 189+ array( $this->pieces[ $index ] ),
 190+ $pieces
 191+ );
 192+ unset( $this->pieces[ $index ] );
 193+ }
 194+
 195+ static::reducePieces( $pieces );
 196+
 197+ array_splice( $this->pieces, $index, 0, $pieces ); // re-numerates keys
 198+ }
 199+
 200+ /**
 201+ * Reduces an array of SemExExpressiveStringPiece elements where possible. This means if the
 202+ * array contains several non-expressive objects in a row, they will be reduced to one instead.
 203+ * This will also make all keys numeric and close gaps.
 204+ *
 205+ * @param SemExExpressiveStringPiece[] $pieces
 206+ * @return int number of reduced pieces
 207+ */
 208+ protected static function reducePieces( array &$pieces ) {
 209+ $lastPieceType = null;
 210+ $i = 0;
 211+ foreach( $pieces as $key => $piece ) {
 212+ if( ! $piece instanceof SemExExpressiveStringPiece
 213+ || $piece->getValue() === ''
 214+ ){
 215+ // remove totally useless empty string or invalid item
 216+ unset( $pieces[ $key ] );
 217+ $i++;
 218+ continue;
 219+ }
 220+
 221+ $thisPieceType = $piece->getType();
 222+
 223+ if(
 224+ $lastPieceType === SEMEX_EXPR_PIECE_STRING
 225+ && $thisPieceType === SEMEX_EXPR_PIECE_STRING
 226+ ) {
 227+ // if two elements in a row are strings, merge them:
 228+ $pieces[ $lastPieceKey ] = new $lastPieceType(
 229+ $pieces[ $lastPieceKey ]->getValue() . $pieces[ $key ]->getValue()
 230+ );
 231+ unset( $pieces[ $key ] );
 232+ $i++;
 233+ } else {
 234+ $lastPieceKey = $key;
 235+ $lastPieceType = $thisPieceType;
 236+ }
 237+ }
 238+ $pieces = array_values( $pieces ); // re-numerate
 239+ return $i;
 240+ }
 241+
 242+ /**
 243+ * Removes pieces of the string starting from a given index to the end or a predefined
 244+ * number of pieces.
 245+ *
 246+ * @param int $offset
 247+ * @param int $length how many pieces to remove. null means all pieces from the $offset
 248+ * to the end. A negative value will preserve pieces that far from the end.
 249+ */
 250+ public function removePieces( $offset, $length = null ) {
 251+ if( empty( $length ) ) {
 252+ $length = count( $offset );
 253+ }
 254+ array_splice( $this->pieces, $offset, $length );
 255+ static::reducePieces( $this->pieces );
 256+ }
 257+
 258+ /**
 259+ * Returns the parser used for certain transformations
 260+ * @return Parser
 261+ */
 262+ public function getParser() {
 263+ return $this->parser;
 264+ }
 265+
 266+ public function setParser( Parser $parser ) {
 267+ $this->parser = $parser;
 268+ }
 269+
 270+ /**
 271+ * Returns the expressive string as wiki text with all expressive pieces resolved but without any
 272+ * further markup, just plain text.
 273+ *
 274+ * @param bool $expressiveIfEmpty whether an expressive textual placeholder should be placed for
 275+ * pieces which have no value. false by default.
 276+ * @return string
 277+ */
 278+ public function getRawText( $expressiveIfEmpty = false ) {
 279+ $result = '';
 280+
 281+ foreach( $this->pieces as $piece ) {
 282+ if( $expressiveIfEmpty && $piece->isUnresolvable() ) {
 283+ $pieceText = $piece->getAbstractRawText();
 284+ } else {
 285+ $pieceText = $piece->getRawText();
 286+ }
 287+ $result .= $pieceText;
 288+ }
 289+ return $result;
 290+ }
 291+
 292+ /**
 293+ * Returns the expressive string as wiki text with all expressive pieces resolved, perhaps with
 294+ * markup built around some pieces.
 295+ *
 296+ * @param bool $expressiveIfEmpty whether an expressive textual placeholder should be placed for
 297+ * pieces which have no value. true by default.
 298+ *
 299+ * @param bool $expressiveIfEmpty
 300+ */
 301+ public function getWikiText(
 302+ $expressiveIfEmpty = true,
 303+ $linked = SemExExpressiveStringOutputOptions::LINK_ALL,
 304+ $showErrors = false
 305+ ) {
 306+ $result = '';
 307+
 308+ foreach( $this->pieces as $piece ) {
 309+ if( ! $expressiveIfEmpty && $piece->isUnresolvable() ) {
 310+ $pieceText = $piece->getAbstractWikiText( $linked, $showErrors );
 311+ } else {
 312+ $pieceText = $piece->getWikiText( $linked, $showErrors );
 313+ }
 314+ $result .= $pieceText;
 315+ }
 316+ return $result;
 317+ }
 318+
 319+ /**
 320+ * same as getRawText() but instead of the resolved meaning of the expressive pieces this will
 321+ * include the abstract representation of all pieces as long as an abstract version is available
 322+ * for the piece type.
 323+ *
 324+ * @return string
 325+ */
 326+ public function getAbstractRawText() {
 327+ $result = '';
 328+
 329+ foreach( $this->pieces as $piece ) {
 330+ $result .= $piece->getAbstractRawText();
 331+ }
 332+ return $result;
 333+ }
 334+
 335+ /**
 336+ * same as getWikiText() but instead of the resolved meaning of the expressive pieces this will
 337+ * include the abstract representation of all pieces as long as an abstract version is available
 338+ * for the piece type.
 339+ *
 340+ * @return string
 341+ */
 342+ public function getAbstractWikiText(
 343+ $linked = SemExExpressiveStringOutputOptions::LINK_ALL,
 344+ $showErrors = false
 345+ ) {
 346+ $result = '';
 347+
 348+ foreach( $this->pieces as $piece ) {
 349+ $result .= $piece->getAbstractWikiText( $linked, $showErrors );
 350+ }
 351+ return $result;
 352+ }
 353+
 354+ /**
 355+ * Returns an output generated by one or several SemExExpressiveStringOutputOptions objects.
 356+ *
 357+ * @param SemExExpressiveStringOutputOptions|null $defaultOption allows to set a option used
 358+ * as default. If set to null the piece types own default options will be used.
 359+ * @param SemExExpressiveStringOutputOptions[]|null[] $options If one option is given, it will
 360+ * be taken for all types of pieces, otherwise an array is expected which holds keys
 361+ * which refer to certain piece types to define a certain option per type. If the
 362+ * value for one type is set to null, it will fall back to its default option. If a
 363+ * type is completely omitted, the $defaultOption will be used for the type, except it
 364+ * is set to null, in this case the types default option will be used.
 365+ *
 366+ * @return string
 367+ */
 368+ public function getOutput( $defaultOption = null, $options = array() ) {
 369+ $result = '';
 370+
 371+ foreach( $this->pieces as $piece ) {
 372+ $pieceType = $piece->getType();
 373+
 374+ if( array_key_exists( $pieceType, $options ) ) {
 375+ // option/fallback for this piece type specified
 376+ $pieceOption = $options[ $pieceType ];
 377+ }
 378+ else {
 379+ // no specific option for this type, use specified default option
 380+ $pieceOption = $defaultOption;
 381+ }
 382+
 383+ if( $pieceOption === null ) {
 384+ // option wasn't set! use default option for this piece type
 385+ $pieceOption = $pieceOption :: getDefaultOutputOptions();
 386+ $options[ $pieceType ] = $pieceOption; // remember for next pice of this type!
 387+ }
 388+
 389+ $result .= $piece->getOutput( $pieceOption );
 390+ }
 391+ return $result;
 392+ }
 393+
 394+ /**
 395+ * Returns which types of expressive string pieces exist. The key number defines the priority
 396+ * of the type within parsing. The highest will be initialized last during the parser process.
 397+ *
 398+ * @return array
 399+ */
 400+ public static function getRegisteredPieceTypes() {
 401+ static $types = null;
 402+ if( $types !== null ) {
 403+ return $types;
 404+ }
 405+
 406+ $types = array();
 407+
 408+ foreach( static::pieceTypeRegistration() as $priority => $typeDef ) {
 409+ $types[ $priority ] = is_array( $typeDef )
 410+ ? $typeDef[0]
 411+ : $typeDef;
 412+ }
 413+
 414+ return $types;
 415+ }
 416+
 417+ /**
 418+ * Returns all registered types in an array as keys and their public names as values. If a
 419+ * registered type doesn't have a name, the type won't be in this list.
 420+ * Use getRegisteredPieceTypes() for getting all types by priority instead.
 421+ *
 422+ * @return array
 423+ */
 424+ public static function getRegisteredPieceTypeNames() {
 425+ static $types = null;
 426+ if( $types !== null ) {
 427+ return $types;
 428+ }
 429+
 430+ $types = array();
 431+
 432+ foreach( static::pieceTypeRegistration() as $typeDef ) {
 433+ if( is_array( $typeDef )
 434+ && ! empty( $typeDef[1] )
 435+ ) {
 436+ $types[ $typeDef[0] ] = $typeDef[1];
 437+ }
 438+ }
 439+
 440+ return $types;
 441+ }
 442+
 443+ /**
 444+ * Returns the class name of a certain registered piece type by the name it's been registered to
 445+ * this class. Some types might not be registered by a name at all.
 446+ *
 447+ * @param name
 448+ *
 449+ * @return string|null piece type class name or null if there is no name identifier for it.
 450+ */
 451+ public static function getRegisteredPieceTypeByName( $name ) {
 452+ $types = static::getRegisteredPieceTypeNames();
 453+ $index = array_search( $name, $types );
 454+ if( $index !== false ) {
 455+ return $index; // the index is the types class name
 456+ }
 457+ return null;
 458+ }
 459+
 460+ protected static function pieceTypeRegistration() {
 461+ static $types = null;
 462+ if( $types !== null ) {
 463+ return $types;
 464+ }
 465+
 466+ $types = array(
 467+ // key defines priority
 468+ 0 => SEMEX_EXPR_PIECE_STRING, // will always be initialized since there is nothing to initialize
 469+ 100 => array( SEMEX_EXPR_PIECE_WIKILINK, 'wikilink' ),
 470+ 1000 => array( SEMEX_EXPR_PIECE_SQRESULT, 'shortqueryresult' ),
 471+ 2000 => array( SEMEX_EXPR_PIECE_SQ, 'shortquery' )
 472+ );
 473+
 474+ // allow other extensions to handle further expressive string pieces
 475+ wfRunHooks( __CLASS__ . 'PieceTypesRegistration' , array( &$types ) );
 476+
 477+ return $types;
 478+ }
 479+
 480+ /**
 481+ * Takes an array with piece types as values and sets their keys according to the registered piece
 482+ * types priorities.
 483+ *
 484+ * @param array $types
 485+ * @return array
 486+ */
 487+ protected static function injectPieceTypePriorities( array $types ) {
 488+ $result = array();
 489+ // go through all registered types and check whether they are within the input array,
 490+ // if so, include it with its original priority
 491+ foreach( static::getRegisteredPieceTypes() as $priority => $type ) {
 492+ if( array_search( $type, $types ) !== false ) {
 493+ $result[ $priority ] = $type;
 494+ }
 495+ }
 496+ return $result;
 497+ }
 498+
 499+ /**
 500+ * Returns which types of expressive string pieces are enabled for this object.
 501+ * This can differ from static::getRegisteredPieceTypes() if specified within the constructor.
 502+ *
 503+ * @return array
 504+ */
 505+ public function getEnabledPieceTypes() {
 506+ return $this->enabledPieceTypes;
 507+ }
 508+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExExpressiveString.php
___________________________________________________________________
Added: svn:eol-style
1509 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExShortQueryResult.php
@@ -0,0 +1,603 @@
 2+<?php
 3+
 4+/**
 5+ * Class describing the result of a 'Semantic Expressiveness' short query. The result can be a
 6+ * Semantic MediaWiki property value of a page or a abstract value in case the requested value
 7+ * doesn't exist.
 8+ * @ToDo: Expand this for having HTML output as well if required
 9+ *
 10+ * @since 0.1
 11+ *
 12+ * @file SemExShortQueryResult.php
 13+ * @ingroup SemanticExpressiveness
 14+ *
 15+ * @licence GNU GPL v3+
 16+ * @author Daniel Werner < danweetz@web.de >
 17+ */
 18+class SemExShortQueryResult {
 19+
 20+ /**
 21+ * @var SemExShortQuery
 22+ */
 23+ protected $query;
 24+ /**
 25+ * @var Parser
 26+ */
 27+ protected $parser;
 28+
 29+ protected $errors = array();
 30+ protected $result = null;
 31+ protected $source = false; // null means missing source, false means not yet datermined
 32+ protected $sourceResult = null; // in case the source is another query, this is its cached result
 33+
 34+ /**
 35+ * Constructor
 36+ *
 37+ * @param SemExShortQuery $query the short query the result should be datermined for. Once a
 38+ * result is datermined, the query itself must not be modified.
 39+ * @param Parser $parser specifies the Parser context in which the result will be released as
 40+ * a more human readable final output over various output functions of the object.
 41+ * @param SMWDataItem[] $result optionally allows to pre-define the result. If not set, the
 42+ * result of the query will be queried on demand. To start the query the result
 43+ * immediately, getRawResult() can be called after construction.
 44+ */
 45+ function __construct( SemExShortQuery $query, Parser $parser, $result = null ) {
 46+ $this->query = $query;
 47+ $this->parser = $parser;
 48+ $this->result = $result;
 49+ // we query the result on demand to save resources!
 50+ }
 51+
 52+ /**
 53+ * Returns whether the result was datermined already. This is false if the result was not accessed
 54+ * yet. This might be of interest if the object gets passed around and the context/time the actual
 55+ * query process happens potentially influences the result.
 56+ *
 57+ * @return bool
 58+ */
 59+ public function queryExecuted() {
 60+ return $this->result !== null;
 61+ }
 62+
 63+ /**
 64+ * Returns an SemExShortQueryAbstractResult object representing the same query.
 65+ *
 66+ * @return SemExShortQueryAbstractResult
 67+ */
 68+ public function getAbstractResult() {
 69+ return new SemExShortQueryAbstractResult( $this->query, $this->parser, $this->result );
 70+ }
 71+
 72+ /**
 73+ * Returns the raw result as array of SMWDataItems. In case the source is not clearly
 74+ * specified, this will return null.
 75+ *
 76+ * @param bool $forceRefresh if set to true, the result will be queried even though it was queried
 77+ * before. Once queried, the result will be cached.
 78+ * @return SMWDataItem[]|null
 79+ */
 80+ public function getRawResult( $forceRefresh = false ) {
 81+ if( ! $forceRefresh && $this->queryExecuted() ) {
 82+ return $this->result;
 83+ }
 84+
 85+ $source = $this->getSource();
 86+ if( $source === null ) {
 87+ return null;
 88+ }
 89+
 90+ $result = null;
 91+ $subject = SMWDIWikiPage::newFromTitle( $source );
 92+ $property = $this->query->getProperty()->getDataItem();
 93+
 94+ // @ToDo: bad idea to use cache AND query, is the cache even needed after recent SMW changes?
 95+
 96+ if( $this->query->getUseCache()
 97+ && $source === $this->parser->getTitle()
 98+ ) {
 99+ // try to get data from current parser process:
 100+ $output = $this->parser->getOutput();
 101+
 102+ // only possible if store is set for page yet:
 103+ if( isset( $output->mSMWData ) ) {
 104+ $result = $output->mSMWData->getPropertyValues( $property );
 105+ }
 106+ }
 107+
 108+ if( empty ( $result ) ) {
 109+ // get the result from a defined SMW data store:
 110+ $result = $this->query->getStore()->getPropertyValues( $subject, $property );
 111+ }
 112+
 113+ $this->result = $result;
 114+ return $result;
 115+ }
 116+
 117+ /**
 118+ * Same as SemExShortQuery::getSource() except this will resolve 'by ref' and current page source
 119+ * types. In case the source is an invalid 'by ref' source null will be returned.
 120+ *
 121+ * @return Title|null
 122+ */
 123+ public function getSource() {
 124+ if( $this->source !== false ) {
 125+ return $this->source;
 126+ }
 127+
 128+ $q = $this->query;
 129+ switch( $q->getSourceType() ) {
 130+ case SemExShortQuery::SOURCE_IS_TITLE:
 131+ $source = $q->getSource();
 132+ break;
 133+
 134+ case SemExShortQuery::SOURCE_FROM_REF:
 135+ // query the source properties value which is the actual source:
 136+ $subQ = clone( $q ); // use same options for caching and store
 137+ $subQ->setProperty( $q->getSource() );
 138+ $subQ->setSource( null ); // current page is source
 139+ /* NO BREAK! */
 140+
 141+ case SemExShortQuery::SOURCE_IS_SHORTQUERY:
 142+ if( ! isset( $subQ ) ) {
 143+ $subQ = $q->getSource();
 144+ }
 145+ $subQR = new self( $subQ, $this->parser );
 146+ $di = $subQR->getRawResult(); // returns all SMWDataItems
 147+ $this->sourceResult = $subQR; // cache this extra
 148+
 149+ if( ! empty( $di ) ) {
 150+ if( count( $di > 1 ) ) {
 151+ // There should only be one DataItem for a short query to make sense!
 152+ $this->addError( 'semex-shortquery-error-byref-has-many-values' );
 153+ }
 154+ $di = $di[0];
 155+ } else {
 156+ $source = null;
 157+ break;
 158+ }
 159+
 160+ if( $di->getDIType() !== SMWDataItem::TYPE_WIKIPAGE ) {
 161+ // should be of type 'Page' to be a proper reference
 162+ $this->addError( 'semex-shortquery-error-byref-has-wrong-type' );
 163+ $source = null;
 164+ break;
 165+ }
 166+ $source = $di->getTitle();
 167+ break;
 168+
 169+ case SemExShortQuery::SOURCE_IS_ESTRING:
 170+ // expressive string as source, e.g. "<?a::<?b::c>>"
 171+ $expressiveSrc = $q->getSource();
 172+
 173+ if( $expressiveSrc->hasUnresolvablePiece() ) {
 174+ // e.g. in case of "<?a::<?b::c>>" whereas "c" doesn't exist.
 175+ // in this case the whole query would be falsified
 176+ $this->addError( 'semex-shortquery-error-failed-nested-queries' );
 177+ $source = null;
 178+ } else {
 179+ $source = Title::newFromText( $expressiveSrc->getRawText() );
 180+ }
 181+ break;
 182+
 183+ case SemExShortQuery::SOURCE_FROM_CONTEXT:
 184+ $source = $this->parser->getTitle();
 185+ break;
 186+ }
 187+
 188+ $this->source = $source;
 189+ return $source;
 190+ }
 191+
 192+ public function getQuery() {
 193+ return $this->query;
 194+ }
 195+
 196+ public function getParser() {
 197+ return $this->parser;
 198+ }
 199+
 200+ /**
 201+ * Returns whether the short query has no result because the requests target page or the
 202+ * requested property on that page do not exist. This is also true if the query definition
 203+ * is faulty and prevents a proper query execution.
 204+ *
 205+ * @return bool
 206+ */
 207+ public function isEmpty() {
 208+ $result = $this->getRawResult();
 209+ return empty( $result );
 210+ }
 211+
 212+ /**
 213+ * Returns whether there have occurred errors of any kind wile processing the query.
 214+ * Note that even though this can have some errors, it isn't automatically a failure. Check
 215+ * isEmpty() to gain information about the queries success.
 216+ *
 217+ * @return bool
 218+ */
 219+ public function hasErrors() {
 220+ $errors = $this->getErrors();
 221+ return !empty( $errors );
 222+ }
 223+
 224+ /**
 225+ * Returns all errors occurred so far
 226+ *
 227+ * @return string[]
 228+ */
 229+ public function getErrors() {
 230+ $errors = $this->errors;
 231+ if( $this->isEmpty() ) {
 232+ // We don't use this message internally since its a ShortQuery feature to change output
 233+ // in case this one occurs
 234+ $errors = array_merge( array( 'semex-shortquery-error-missing-property' ), $errors );
 235+ }
 236+ return $errors;
 237+ }
 238+
 239+ /**
 240+ * This will add a new error or a set of error descriptions to the object.
 241+ *
 242+ * @param string|string[] addError
 243+ */
 244+ protected function addError( $error ) {
 245+ if( is_array( $error ) ) {
 246+ $this->errors = array_merge( $this->errors, $error );
 247+ } else {
 248+ $this->errors[] = $error;
 249+ }
 250+ }
 251+
 252+ /**
 253+ * Returns a string containing all error messages as a tooltip, or an empty string if no
 254+ * errors occurred.
 255+ *
 256+ * @return string
 257+ */
 258+ public function getErrorText() {
 259+ return smwfEncodeMessages( $this->getErrors() );
 260+ }
 261+
 262+ /**
 263+ * Same as getErrorText() except this won't output the message about the requested property not
 264+ * existing on the page.
 265+ */
 266+ protected function getErrorTextForFormattedSQ() {
 267+ smwfEncodeMessages( $this->errors );
 268+ }
 269+
 270+ /**
 271+ * Returns the result as unformatted plain text. In case the result consists of several data values,
 272+ * all of them will be put together separated by a comma.
 273+ *
 274+ * @return string
 275+ */
 276+ public function getRawText() {
 277+ if( $this->isEmpty() ) {
 278+ return '';
 279+ }
 280+ $values = array();
 281+ foreach( $this->getRawResult() as $dataItem ) {
 282+ $dataValue = SMWDataValueFactory::newDataItemValue( $dataItem, null );
 283+ $values[] = trim( $dataValue->getWikiValue() );
 284+ }
 285+ return implode( ', ', $values );
 286+ }
 287+
 288+ /**
 289+ * Returns the result as a short wiki text representation without informational HTML markup,
 290+ * even though it would be usable within wiki markup.
 291+ * getWikiText() can be used to get the completely formatted wiki markup
 292+ *
 293+ * @param mixed $linked Allows one of
 294+ * SemExShortQueryOutputOptions::LINK_NONE
 295+ * SemExShortQueryOutputOptions::LINK_ALL
 296+ * SemExShortQueryOutputOptions::LINK_TOPIC
 297+ * @param bool $showErrors can be set to true to show errors. Off by default.
 298+ *
 299+ * @return string
 300+ */
 301+ public function getShortWikiText(
 302+ $linked = SemExShortQueryOutputOptions::LINK_ALL,
 303+ $showErrors = false
 304+ ) {
 305+ if( $this->isEmpty() ) {
 306+ return '';
 307+ }
 308+ $values = array();
 309+ foreach( $this->getRawResult() as $dataItem ) {
 310+ $dataValue = SMWDataValueFactory::newDataItemValue( $dataItem, null );
 311+ $values[] = trim( $dataValue->getShortWikiText( $linked === SemExShortQueryOutputOptions::LINK_ALL ) );
 312+ }
 313+ $out = implode( ', ', $values );
 314+
 315+ if( $out !== '' && $linked === SemExShortQueryOutputOptions::LINK_TOPIC ) {
 316+ // wrap whole result in one link to the source
 317+ $topic = $this->getSource();
 318+ $out = "[[:{$topic}|{$out}]]";
 319+ }
 320+
 321+ if( $showErrors ) {
 322+ // show all errors, also the one saying property doesn't exist ($out === '')
 323+ $out .= $this->getErrorText();
 324+ }
 325+
 326+ return $out;
 327+ }
 328+
 329+ /**
 330+ * Returns the full wiki text output with full markup, normally wrapped in some lightweight HTML
 331+ * tags marked as successful Short Query. In case the query failed, there will be some similar
 332+ * output with an abstract representation of the requested value.
 333+ * In any case, the output will be including all information for later JavaScript processing or
 334+ * use with '?to?!' parser function.
 335+ *
 336+ * @param mixed $linked Allows one of
 337+ * SemExShortQueryOutputOptions::LINK_NONE
 338+ * SemExShortQueryOutputOptions::LINK_ALL
 339+ * SemExShortQueryOutputOptions::LINK_TOPIC
 340+ * @param bool $showErrors
 341+ *
 342+ * @return string
 343+ *
 344+ * @todo: rename 'value' in 'rawResult' and 'abstractValue' in 'abstractResult'
 345+ */
 346+ public function getWikiText(
 347+ $linked = SemExShortQueryOutputOptions::LINK_ALL,
 348+ $showErrors = true
 349+ ) {
 350+ return $this->getWikiText_internal( $linked, $showErrors, false );
 351+ }
 352+
 353+ // $enforceAbstract parameter to reduce code in 'SemExShortQueryAbstractResult' sub-class
 354+ protected function getWikiText_internal( $linked, $showErrors, $enforceAbstract = false ) {
 355+ $out = '';
 356+
 357+ // if abstract is enforced, we won't query at all!
 358+ $showAbstract = $enforceAbstract || $this->isEmpty();
 359+ $sqClasses = array( 'shortQuery' );
 360+
 361+ if( $showAbstract ) {
 362+ $sqClasses[] = 'abstractShortQuery';
 363+ if( ! $enforceAbstract ) {
 364+ $sqClasses[] = 'failedShortQuery';
 365+ }
 366+ }
 367+
 368+ $out .= HTML::openElement( 'span', array( 'class' => implode( ' ', $sqClasses ) ) );
 369+
 370+ // get all important information to re-create this object:
 371+ $out .= $this->getSerialization();
 372+
 373+ if( ! $showAbstract ) {
 374+ // data for formatted result:
 375+ // ( can't quote this since it might contain html data! TODO: perhaps we could just strip this as HTML )
 376+ // ( this is a problem when using ?to?! having some invalid stuff in here for any reason )
 377+ $out .= HTML::rawElement( 'span', array( 'class' => 'result'), $this->getShortWikiText( $linked, $showErrors ) );
 378+ }
 379+ else {
 380+ $out .= $this->getAbstractResult()->getShortWikiText( $linked, $showErrors );
 381+ }
 382+
 383+ if( $showErrors && !empty( $this->errors ) ) {
 384+ // add errors, except the one saying that the whole thing is a failure:
 385+ $out .= HTML::rawElement( 'span', array( 'class' => 'errors' ), $this->getErrorTextForFormattedSQ() );
 386+ }
 387+
 388+ $out .= HTML::closeElement( 'span' );
 389+ return $out;
 390+ }
 391+
 392+ /**
 393+ * Returns a serialized string optimazied for usage as WikiText or as HTML markup without actually
 394+ * producing any visible output when used properly.
 395+ *
 396+ * @Note: This could be done nicer with HTML5
 397+ *
 398+ * @return string
 399+ */
 400+ public function getSerialization() {
 401+ // query target page:
 402+ $source = ( $this->getSource() === null ) ? '' : $this->getSource()->getPrefixedText();
 403+ $out = HTML::element( 'span', array( 'class' => 'source', 'title' => $source ) );
 404+
 405+ // queried property:
 406+ $out .= HTML::element( 'span', array( 'class' => 'type', 'title' => $this->query->getProperty()->getDataItem()->getLabel() ) );
 407+
 408+ $storeName = $this->query->getStoreName();
 409+ if( $storeName !== '' ) {
 410+ // only add information about store if default store not in use
 411+ $out .= HTML::element( 'span', array( 'class' => 'storeSource', 'title' => $storeName ) );
 412+ }
 413+
 414+ if( ! $this->isEmpty() ) {
 415+ // data for raw result:
 416+ $rawValues = '';
 417+ foreach( $this->getRawResult() as $dataItem ) {
 418+ // separate all data values by putting them in their own span each
 419+ $dataValue = SMWDataValueFactory::newDataItemValue( $dataItem, null );
 420+ $dataValue = trim( $dataValue->getWikiValue() );
 421+ $rawValues .= HTML::element( 'span', array( 'title' => $dataValue ) );
 422+ /*
 423+ * @ToDo: FIXME: Might be a good idea to simply use DataItem default serialization,
 424+ * on the other hand, this would be kind of useless for JavaScript.
 425+ */
 426+ }
 427+ $out .= HTML::rawElement( 'span', array( 'class' => 'value' ), $rawValues );
 428+ }
 429+
 430+ return $out;
 431+ }
 432+
 433+ /**
 434+ * Returns the output in a pre-defined exactly specified way by a SemExShortQueryResultOptions
 435+ * object.
 436+ *
 437+ * @ToDo: implement SemExShortQueryOutputOptions::getFormat() if required
 438+ *
 439+ * @return string
 440+ */
 441+ public function getOutput( SemExShortQueryOutputOptions $options ) {
 442+ $useRaw = $options->getFormat() === SemExShortQueryOutputOptions::FORMAT_RAW;
 443+ $showInfo = $options->getShowInfo();
 444+ $linked = $options->getLink();
 445+ $errors = $options->getShowErrors();
 446+ $abstract = $options->getShowAbstract();
 447+
 448+ if( $abstract === SemExShortQueryOutputOptions::NO_ABSTRACT
 449+ && $this->isEmpty()
 450+ ) {
 451+ // don't display abstract values, so nothing to display except...
 452+ if( $errors && !$useRaw ) {
 453+ // ...display errors at least, including information why this "failed"
 454+ return $this->getErrorText();
 455+ } else {
 456+ return '';
 457+ }
 458+ }
 459+
 460+ // if only abstract info is required, get this results abstract representation
 461+ $abstractInUse =
 462+ $abstract === SemExShortQueryOutputOptions::ABSTRACT_ONLY
 463+ || ( $this->isEmpty() && $abstract === SemExShortQueryOutputOptions::ABSTRACT_IF_FAILURE );
 464+
 465+ $result = $abstractInUse
 466+ ? $this->getAbstractResult()
 467+ : $this;
 468+
 469+ if( $useRaw ) {
 470+ return ( $result->getRawText() );
 471+ }
 472+
 473+ if( $showInfo ) {
 474+ // output result wrapped with max markup and information
 475+ return $result->getWikiText( $linked, $errors );
 476+ }
 477+ else {
 478+ // light version
 479+ return $result->getShortWikiText( $linked, $errors );
 480+ }
 481+ }
 482+
 483+ /**
 484+ * Factory function to get an existing result from its full wiki or HTML output by reading the
 485+ * produced tag information.
 486+ *
 487+ * @param DOMNode $node
 488+ * @param Parser $parser
 489+ * @param bool $refreshData whether the result should be re-queried even though the original result
 490+ * is available from the given DOM information.
 491+ *
 492+ * @return SemExShortQueryResult
 493+ */
 494+ public static function newFromDOM( DOMNode $node, Parser $parser, $refreshData = false ) {
 495+ $prop = self::extractInfoFromDOM( $node, 'type' );
 496+ $source = self::extractInfoFromDOM( $node, 'source' );
 497+
 498+ if( $prop === null || $source === null ) {
 499+ // ERROR
 500+ throw new SemExShortQueryResultException( 'Insufficient input data.' );
 501+ }
 502+
 503+ $origQuery = SemExShortQuery::newFromParamsArray( array(
 504+ 'property' => $prop,
 505+ 'from' => $source,
 506+ 'source' => self::extractInfoFromDOM( $node, 'storeSource' ),
 507+ ) );
 508+
 509+ $result = null;
 510+
 511+ if( ! $refreshData ) {
 512+ $result = array();
 513+
 514+ // fill result from DOM information:
 515+ $origResultContainer = self::extractInfoFromDOM( $node, 'value', true );
 516+
 517+ if( $origResultContainer->hasChildNodes() ) {
 518+ $propDi = $origQuery->getProperty()->getDataItem();
 519+
 520+ // each DataValue inside its own <span title="data" />
 521+ foreach( $origResultContainer->child_nodes() as $resultNode ) {
 522+ if( ! $resultNode->hasAttributes() ) {
 523+ continue;
 524+ }
 525+ $result = trim( $resultNode->attributes->getNamedItem( 'title' ) );
 526+ if( $result === '' ) {
 527+ continue;
 528+ }
 529+ $sqResult->result[] = SMWDataValueFactory::newPropertyObjectValue(
 530+ $propDi, $result, $caption
 531+ );
 532+ }
 533+ }
 534+ }
 535+
 536+ return new self( $origQuery, $parser, $result );
 537+ }
 538+
 539+ /**
 540+ * Creates a new SemExShortQueryResult from a serialized string given by
 541+ * SemExShortQueryResult::getSerialization().
 542+ *
 543+ * @param string $serialization
 544+ * @param Parser $parser
 545+ *
 546+ * @return SemExShortQueryResult
 547+ */
 548+ public static function newFromSerialization( $serialization, Parser $parser ) {
 549+ $strHtml = "<body>$serialization</body>";
 550+
 551+ $xmlDoc = new DOMDocument();
 552+ $xmlDoc->strictErrorChecking = false;
 553+
 554+ wfSuppressWarnings();
 555+ $validDom = $xmlDoc->loadXML( $part );
 556+ wfRestoreWarnings();
 557+
 558+ if( ! $validDom ) {
 559+ // ERROR
 560+ throw new SemExShortQueryResultException( "Invalid serialized string '$serialization' given." );
 561+ }
 562+
 563+ return SemExShortQueryResult::newFromDOM( $xmlDoc->documentElement, $parser );
 564+ }
 565+
 566+ /**
 567+ * Helper for getting information about the short query result from its DOM representation.
 568+ *
 569+ * @param DOMNode $node
 570+ * @param string $info
 571+ * @param bool $getNode if set to true, this will return the DOMNode containing the
 572+ * requested information instead of just returning the 'title' attribute content.
 573+ *
 574+ * @return string|DOMNodeList|null
 575+ */
 576+ protected static function extractInfoFromDOM( DOMNode $node, $info, $getNode = false ) {
 577+ if( ! $node->hasChildNodes() ) {
 578+ return null;
 579+ }
 580+ $xpath = new DOMXpath( $node );
 581+ $nodes = $xpath->query( "/*/*[@class=\"{$info}\"][@title][1]" );
 582+
 583+ if( $nodes->length < 1 ) {
 584+ return null;
 585+ }
 586+
 587+ $node = $nodes->item( 0 );
 588+ if( $getNode ) {
 589+ return $node;
 590+ }
 591+
 592+ $result = trim( $node->attributes->getNamedItem( 'title' ) );
 593+ if( $result === '' ) {
 594+ return null;
 595+ }
 596+ return $result;
 597+ }
 598+}
 599+
 600+/**
 601+ * Exception to be thrown when short query result creation fails due to bad input.
 602+ */
 603+class SemExShortQueryResultException extends MWException {
 604+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExShortQueryResult.php
___________________________________________________________________
Added: svn:eol-style
1605 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExShortQuery.php
@@ -0,0 +1,230 @@
 2+<?php
 3+
 4+/**
 5+ * Class describing a 'Semantic Expressiveness' short query.
 6+ * SemExShortQueryProcessor::getResultFromQuery() can be used to get a short queries result.
 7+ *
 8+ * @since 0.1
 9+ *
 10+ * @file SemExShortQuery.php
 11+ * @ingroup SemanticExpressiveness
 12+ *
 13+ * @author Daniel Werner < danweetz@web.de >
 14+ */
 15+class SemExShortQuery extends SemExPFParamsBasedFactory {
 16+
 17+ protected static $pfParamsValidatorElement = 'SemEx Short Query';
 18+
 19+ protected $property;
 20+ protected $source;
 21+ protected $store = null;
 22+ protected $useCache = true;
 23+
 24+ const SOURCE_IS_TITLE = 1;
 25+ const SOURCE_FROM_CONTEXT = 2; // source from current page (depending on Parser object)
 26+ const SOURCE_FROM_REF = 3; // source from another property of the current page
 27+ const SOURCE_IS_SHORTQUERY = 4;
 28+ const SOURCE_IS_ESTRING = 5; // ESTRING = ExpressiveString
 29+
 30+ /**
 31+ * Constructor
 32+ *
 33+ * @param SMWPropertyValue $property the property which should be queried
 34+ * @param Title|SMWPropertyValue|SemExExpressiveString|null where the property should be queried from.
 35+ * See setSource() for details.
 36+ */
 37+ public function __construct( SMWPropertyValue $property, $source = null ) {
 38+ $this->property = $property;
 39+ $this->source = $source; // null implies current page
 40+ }
 41+
 42+ /**
 43+ * Sets the source from where a specific property should be queried from. This can consist of different
 44+ * types of values. The possible types and their meanings:
 45+ * Title: The titles will be searched for the source property.
 46+ * SMWPropertyValue: SMW property which should be of type 'Page'. In that case the current pages
 47+ * property value will be taken as source for the query.
 48+ * SemExShortQuery: The result of another short query is taken as source.
 49+ * SemExExpressiveString: Source is a expressive string which can contain further short queries. This
 50+ * makes the short query highly expressive as it's possible to trace the source
 51+ * of what should be queried.
 52+ * null: implies that the property should be queried from the query processors current
 53+ * context page.
 54+ *
 55+ * @param Title|SMWPropertyValue|SemExShortQuery|SemExExpressiveString|null $source
 56+ */
 57+ public function setSource( $source ) {
 58+ $this->source = $source;
 59+ }
 60+
 61+ /**
 62+ * Returns the source the specific property should be queried from.
 63+ * @return Title|SMWPropertyValue|SemExExpressiveString|null
 64+ */
 65+ public function getSource() {
 66+ return $this->source;
 67+ }
 68+
 69+ /**
 70+ * Returns the kind of source the query will get the requested property from. the following types
 71+ * are possible:
 72+ *
 73+ * self::SOURCE_IS_TITLE - Implies that the property will be taken from a certain page
 74+ * self::SOURCE_FROM_REF - Implies that the property will be taken from a page where another
 75+ * property on the queries context page refers to.
 76+ * self::SOURCE_FROM_CONTEXT - Implies that the property will be taken from the page where the
 77+ * query is defined at.
 78+ * self::SOURCE_IS_ESTRING - Implies that the property will be taken from an expressive string,
 79+ * possibly containing further short queries.
 80+ * self::SOURCE_IS_SHORTQUERY - Implies that the property will be taken from the result of another
 81+ * short query.
 82+ *
 83+ * @return boolean
 84+ */
 85+ public function getSourceType() {
 86+ if( $this->source === null ) {
 87+ return self::SOURCE_FROM_CONTEXT;
 88+ }
 89+ if( $this->source instanceof SMWPropertyValue ) {
 90+ return self::SOURCE_FROM_REF;
 91+ }
 92+ if( $this->source instanceof self ) {
 93+ return self::SOURCE_IS_SHORTQUERY;
 94+ }
 95+ if( $this->source instanceof SemExExpressiveString ) {
 96+ return self::SOURCE_IS_ESTRING;
 97+ }
 98+ return self::SOURCE_IS_TITLE;
 99+ }
 100+
 101+ /**
 102+ * Function to define for which property should be queried.
 103+ * @param SMWPropertyValue $property
 104+ */
 105+ public function setProperty( SMWPropertyValue $property ) {
 106+ $this->property = $property;
 107+ }
 108+
 109+ /**
 110+ * Returns the property for which the query is asking.
 111+ * @return SMWPropertyValue
 112+ */
 113+ public function getProperty() {
 114+ return $this->property;
 115+ }
 116+
 117+ /**
 118+ * Defines whether queries having the same source as the page they are defined on should
 119+ * consider properties collected during the page rendering which are not stored within the
 120+ * database yet.
 121+ *
 122+ * @param bool $val
 123+ * @return bool previous value
 124+ */
 125+ public function setUseCache( $val ) {
 126+ return wfSetVar( $this->useCache, $val );
 127+ }
 128+
 129+ /**
 130+ * @see SemExShortQuery::setUseCache()
 131+ * @return bool
 132+ */
 133+ public function getUseCache() {
 134+ return $this->useCache;
 135+ }
 136+
 137+ /**
 138+ * Sets the Store which should be the source for the query.
 139+ * Consider that depending on the cache option, the store won't even have an effect.
 140+ *
 141+ * @param SMWStore $val
 142+ * @return SMWStore
 143+ */
 144+ public function setStore( SMWStore $val ) {
 145+ return wfSetVar( $this->store, $val );
 146+ }
 147+
 148+ /**
 149+ * @see SemExShortQuery::setStore()
 150+ * @return SMWStore
 151+ */
 152+ public function getStore() {
 153+ if( $this->store === null ) {
 154+ $this->store = smwfGetStore();
 155+ }
 156+ return $this->store;
 157+ }
 158+
 159+ /**
 160+ * Returns the associated store name which identifies the store within $smwgQuerySources
 161+ * A empty string refers to the default store. Returns false in case the store in use is
 162+ * not known to $smwgQuerySources (which should not happen normally)
 163+ *
 164+ * @return string|false
 165+ */
 166+ public function getStoreName() {
 167+ if( $this->store === null
 168+ || $this->store === smwfGetStore()
 169+ ) {
 170+ return ''; // default store
 171+ }
 172+
 173+ global $smwgQuerySources;
 174+
 175+ $storeClass = get_class( $this->store );
 176+ $index = array_search( $storeClass, $smwgQuerySources ); // false if unknown
 177+
 178+ return $index;
 179+ }
 180+
 181+ /**
 182+ * @see SemExPFParamsBasedFactory::newFromValidatedParams()
 183+ */
 184+ public static function newFromValidatedParams( array $params ) {
 185+ $query = new self( $params['property'] );
 186+
 187+ if( $params['from ref'] ) {
 188+ $query->setSource( $params['from ref'] );
 189+ }
 190+ elseif( $params['from'] ) {
 191+ $query->setSource( $params['from'] );
 192+ }
 193+
 194+ $query->setUseCache( $params['cache'] );
 195+ $query->setStore( $params['source'] );
 196+
 197+ return $query;
 198+ }
 199+
 200+ /**
 201+ * Returns a description of all allowed function Parameters representing a SemExShortQuery.
 202+ */
 203+ public static function getPFParams() {
 204+ $params = array();
 205+
 206+ $params['property'] = new Parameter( 'property' );
 207+ $params['property']->addCriteria( new SemExCriterionIsProperty() );
 208+ $params['property']->addManipulations( new SemExParamManipulationProperty() );
 209+
 210+ $params['from'] = new Parameter( 'from', Parameter::TYPE_TITLE );
 211+ $params['from']->setDefault( false, false );
 212+
 213+ $params['from ref'] = new Parameter( 'from ref' );
 214+ $params['from ref']->addCriteria( // only allow properties of type 'Page' for this!
 215+ new SemExCriterionIsProperty( '_wpg' )
 216+ );
 217+ $params['from ref']->addManipulations( new SemExParamManipulationProperty() );
 218+ $params['from ref']->setDefault( false, false );
 219+
 220+ $params['cache'] = new Parameter( 'cache', Parameter::TYPE_BOOLEAN );
 221+ $params['cache']->setDefault( true );
 222+
 223+ // this has nothing to do with set/getSource but delivers the value for set/getStore:
 224+ $params['source'] = new Parameter( 'source' );
 225+ $params['source']->addCriteria( new SemExCriterionIsQuerySource() );
 226+ $params['source']->addManipulations( new SemExParamManipulationQuerySource() );
 227+ $params['source']->setDefault( smwfGetStore(), false );
 228+
 229+ return $params;
 230+ }
 231+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExShortQuery.php
___________________________________________________________________
Added: svn:eol-style
1232 + native
Index: trunk/extensions/SemanticExpressiveness/includes/SemExShortQueryProcessor.php
@@ -0,0 +1,60 @@
 2+<?php
 3+
 4+/**
 5+ * Factory class to generate and execute 'Semantic Expressiveness' short queries and return their
 6+ * result as SemExShortQueryResult object or in directly in a serialized form.
 7+ *
 8+ * @since 0.1
 9+ *
 10+ * @file SemExShortQueryProcessor.php
 11+ * @ingroup SemanticExpressiveness
 12+ *
 13+ * @author Daniel Werner < danweetz@web.de >
 14+ */
 15+class SemExShortQueryProcessor {
 16+
 17+ /**
 18+ * Processes a 'Semantic Expressiveness' Short Qery as given by an array of parameters as usually
 19+ * given by the '?' and '?!' parser functions.
 20+ *
 21+ * @param parser Parser
 22+ * @param rawParams array unprocessed parameters
 23+ *
 24+ * @return array
 25+ */
 26+ public static function getResultFromFunctionParams( Parser $parser, array $rawParams ) {
 27+
 28+ $query = SemExShortQuery::newFromPFParams( $rawParams );
 29+ $options = SemExShortQueryOutputOptions::newFromPFParams( $rawParams );
 30+
 31+ // @ToDo: Check for validation errors at some point
 32+
 33+ return self::getResultFromQuery( $parser, $query, $options );
 34+ }
 35+
 36+ /**
 37+ * Processes a 'Semantic Expressiveness' Short Query and returns the result which can contain
 38+ * either a valid result or an abstract value.
 39+ * Optionally there can be a SemExShortQueryResultOptions object passed to retain a certain
 40+ * kind of output from the short query.
 41+ *
 42+ * @param Parser $parser
 43+ * @param SemExShortQuery $query
 44+ * @param SemExShortQueryOutputOptions $options
 45+ *
 46+ * @return SemExShortQueryResult|String
 47+ */
 48+ public static function getResultFromQuery(
 49+ Parser $parser,
 50+ SemExShortQuery $query,
 51+ $options = null
 52+ ) {
 53+ $result = new SemExShortQueryResult( $query, $parser );
 54+
 55+ if( $options !== null ) {
 56+ return $result->getOutput( $options );
 57+ }
 58+
 59+ return $result;
 60+ }
 61+}
Property changes on: trunk/extensions/SemanticExpressiveness/includes/SemExShortQueryProcessor.php
___________________________________________________________________
Added: svn:eol-style
162 + native
Index: trunk/extensions/SemanticExpressiveness/COPYING
@@ -0,0 +1,679 @@
 2+Semantic Expressiveness
 3+Copyright (C) 2012 by Daniel Werner
 4+
 5+The license text below "----" applies to all files within this distribution
 6+----
 7+ GNU GENERAL PUBLIC LICENSE
 8+ Version 3, 29 June 2007
 9+
 10+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 11+ Everyone is permitted to copy and distribute verbatim copies
 12+ of this license document, but changing it is not allowed.
 13+
 14+ Preamble
 15+
 16+ The GNU General Public License is a free, copyleft license for
 17+software and other kinds of works.
 18+
 19+ The licenses for most software and other practical works are designed
 20+to take away your freedom to share and change the works. By contrast,
 21+the GNU General Public License is intended to guarantee your freedom to
 22+share and change all versions of a program--to make sure it remains free
 23+software for all its users. We, the Free Software Foundation, use the
 24+GNU General Public License for most of our software; it applies also to
 25+any other work released this way by its authors. You can apply it to
 26+your programs, too.
 27+
 28+ When we speak of free software, we are referring to freedom, not
 29+price. Our General Public Licenses are designed to make sure that you
 30+have the freedom to distribute copies of free software (and charge for
 31+them if you wish), that you receive source code or can get it if you
 32+want it, that you can change the software or use pieces of it in new
 33+free programs, and that you know you can do these things.
 34+
 35+ To protect your rights, we need to prevent others from denying you
 36+these rights or asking you to surrender the rights. Therefore, you have
 37+certain responsibilities if you distribute copies of the software, or if
 38+you modify it: responsibilities to respect the freedom of others.
 39+
 40+ For example, if you distribute copies of such a program, whether
 41+gratis or for a fee, you must pass on to the recipients the same
 42+freedoms that you received. You must make sure that they, too, receive
 43+or can get the source code. And you must show them these terms so they
 44+know their rights.
 45+
 46+ Developers that use the GNU GPL protect your rights with two steps:
 47+(1) assert copyright on the software, and (2) offer you this License
 48+giving you legal permission to copy, distribute and/or modify it.
 49+
 50+ For the developers' and authors' protection, the GPL clearly explains
 51+that there is no warranty for this free software. For both users' and
 52+authors' sake, the GPL requires that modified versions be marked as
 53+changed, so that their problems will not be attributed erroneously to
 54+authors of previous versions.
 55+
 56+ Some devices are designed to deny users access to install or run
 57+modified versions of the software inside them, although the manufacturer
 58+can do so. This is fundamentally incompatible with the aim of
 59+protecting users' freedom to change the software. The systematic
 60+pattern of such abuse occurs in the area of products for individuals to
 61+use, which is precisely where it is most unacceptable. Therefore, we
 62+have designed this version of the GPL to prohibit the practice for those
 63+products. If such problems arise substantially in other domains, we
 64+stand ready to extend this provision to those domains in future versions
 65+of the GPL, as needed to protect the freedom of users.
 66+
 67+ Finally, every program is threatened constantly by software patents.
 68+States should not allow patents to restrict development and use of
 69+software on general-purpose computers, but in those that do, we wish to
 70+avoid the special danger that patents applied to a free program could
 71+make it effectively proprietary. To prevent this, the GPL assures that
 72+patents cannot be used to render the program non-free.
 73+
 74+ The precise terms and conditions for copying, distribution and
 75+modification follow.
 76+
 77+ TERMS AND CONDITIONS
 78+
 79+ 0. Definitions.
 80+
 81+ "This License" refers to version 3 of the GNU General Public License.
 82+
 83+ "Copyright" also means copyright-like laws that apply to other kinds of
 84+works, such as semiconductor masks.
 85+
 86+ "The Program" refers to any copyrightable work licensed under this
 87+License. Each licensee is addressed as "you". "Licensees" and
 88+"recipients" may be individuals or organizations.
 89+
 90+ To "modify" a work means to copy from or adapt all or part of the work
 91+in a fashion requiring copyright permission, other than the making of an
 92+exact copy. The resulting work is called a "modified version" of the
 93+earlier work or a work "based on" the earlier work.
 94+
 95+ A "covered work" means either the unmodified Program or a work based
 96+on the Program.
 97+
 98+ To "propagate" a work means to do anything with it that, without
 99+permission, would make you directly or secondarily liable for
 100+infringement under applicable copyright law, except executing it on a
 101+computer or modifying a private copy. Propagation includes copying,
 102+distribution (with or without modification), making available to the
 103+public, and in some countries other activities as well.
 104+
 105+ To "convey" a work means any kind of propagation that enables other
 106+parties to make or receive copies. Mere interaction with a user through
 107+a computer network, with no transfer of a copy, is not conveying.
 108+
 109+ An interactive user interface displays "Appropriate Legal Notices"
 110+to the extent that it includes a convenient and prominently visible
 111+feature that (1) displays an appropriate copyright notice, and (2)
 112+tells the user that there is no warranty for the work (except to the
 113+extent that warranties are provided), that licensees may convey the
 114+work under this License, and how to view a copy of this License. If
 115+the interface presents a list of user commands or options, such as a
 116+menu, a prominent item in the list meets this criterion.
 117+
 118+ 1. Source Code.
 119+
 120+ The "source code" for a work means the preferred form of the work
 121+for making modifications to it. "Object code" means any non-source
 122+form of a work.
 123+
 124+ A "Standard Interface" means an interface that either is an official
 125+standard defined by a recognized standards body, or, in the case of
 126+interfaces specified for a particular programming language, one that
 127+is widely used among developers working in that language.
 128+
 129+ The "System Libraries" of an executable work include anything, other
 130+than the work as a whole, that (a) is included in the normal form of
 131+packaging a Major Component, but which is not part of that Major
 132+Component, and (b) serves only to enable use of the work with that
 133+Major Component, or to implement a Standard Interface for which an
 134+implementation is available to the public in source code form. A
 135+"Major Component", in this context, means a major essential component
 136+(kernel, window system, and so on) of the specific operating system
 137+(if any) on which the executable work runs, or a compiler used to
 138+produce the work, or an object code interpreter used to run it.
 139+
 140+ The "Corresponding Source" for a work in object code form means all
 141+the source code needed to generate, install, and (for an executable
 142+work) run the object code and to modify the work, including scripts to
 143+control those activities. However, it does not include the work's
 144+System Libraries, or general-purpose tools or generally available free
 145+programs which are used unmodified in performing those activities but
 146+which are not part of the work. For example, Corresponding Source
 147+includes interface definition files associated with source files for
 148+the work, and the source code for shared libraries and dynamically
 149+linked subprograms that the work is specifically designed to require,
 150+such as by intimate data communication or control flow between those
 151+subprograms and other parts of the work.
 152+
 153+ The Corresponding Source need not include anything that users
 154+can regenerate automatically from other parts of the Corresponding
 155+Source.
 156+
 157+ The Corresponding Source for a work in source code form is that
 158+same work.
 159+
 160+ 2. Basic Permissions.
 161+
 162+ All rights granted under this License are granted for the term of
 163+copyright on the Program, and are irrevocable provided the stated
 164+conditions are met. This License explicitly affirms your unlimited
 165+permission to run the unmodified Program. The output from running a
 166+covered work is covered by this License only if the output, given its
 167+content, constitutes a covered work. This License acknowledges your
 168+rights of fair use or other equivalent, as provided by copyright law.
 169+
 170+ You may make, run and propagate covered works that you do not
 171+convey, without conditions so long as your license otherwise remains
 172+in force. You may convey covered works to others for the sole purpose
 173+of having them make modifications exclusively for you, or provide you
 174+with facilities for running those works, provided that you comply with
 175+the terms of this License in conveying all material for which you do
 176+not control copyright. Those thus making or running the covered works
 177+for you must do so exclusively on your behalf, under your direction
 178+and control, on terms that prohibit them from making any copies of
 179+your copyrighted material outside their relationship with you.
 180+
 181+ Conveying under any other circumstances is permitted solely under
 182+the conditions stated below. Sublicensing is not allowed; section 10
 183+makes it unnecessary.
 184+
 185+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
 186+
 187+ No covered work shall be deemed part of an effective technological
 188+measure under any applicable law fulfilling obligations under article
 189+11 of the WIPO copyright treaty adopted on 20 December 1996, or
 190+similar laws prohibiting or restricting circumvention of such
 191+measures.
 192+
 193+ When you convey a covered work, you waive any legal power to forbid
 194+circumvention of technological measures to the extent such circumvention
 195+is effected by exercising rights under this License with respect to
 196+the covered work, and you disclaim any intention to limit operation or
 197+modification of the work as a means of enforcing, against the work's
 198+users, your or third parties' legal rights to forbid circumvention of
 199+technological measures.
 200+
 201+ 4. Conveying Verbatim Copies.
 202+
 203+ You may convey verbatim copies of the Program's source code as you
 204+receive it, in any medium, provided that you conspicuously and
 205+appropriately publish on each copy an appropriate copyright notice;
 206+keep intact all notices stating that this License and any
 207+non-permissive terms added in accord with section 7 apply to the code;
 208+keep intact all notices of the absence of any warranty; and give all
 209+recipients a copy of this License along with the Program.
 210+
 211+ You may charge any price or no price for each copy that you convey,
 212+and you may offer support or warranty protection for a fee.
 213+
 214+ 5. Conveying Modified Source Versions.
 215+
 216+ You may convey a work based on the Program, or the modifications to
 217+produce it from the Program, in the form of source code under the
 218+terms of section 4, provided that you also meet all of these conditions:
 219+
 220+ a) The work must carry prominent notices stating that you modified
 221+ it, and giving a relevant date.
 222+
 223+ b) The work must carry prominent notices stating that it is
 224+ released under this License and any conditions added under section
 225+ 7. This requirement modifies the requirement in section 4 to
 226+ "keep intact all notices".
 227+
 228+ c) You must license the entire work, as a whole, under this
 229+ License to anyone who comes into possession of a copy. This
 230+ License will therefore apply, along with any applicable section 7
 231+ additional terms, to the whole of the work, and all its parts,
 232+ regardless of how they are packaged. This License gives no
 233+ permission to license the work in any other way, but it does not
 234+ invalidate such permission if you have separately received it.
 235+
 236+ d) If the work has interactive user interfaces, each must display
 237+ Appropriate Legal Notices; however, if the Program has interactive
 238+ interfaces that do not display Appropriate Legal Notices, your
 239+ work need not make them do so.
 240+
 241+ A compilation of a covered work with other separate and independent
 242+works, which are not by their nature extensions of the covered work,
 243+and which are not combined with it such as to form a larger program,
 244+in or on a volume of a storage or distribution medium, is called an
 245+"aggregate" if the compilation and its resulting copyright are not
 246+used to limit the access or legal rights of the compilation's users
 247+beyond what the individual works permit. Inclusion of a covered work
 248+in an aggregate does not cause this License to apply to the other
 249+parts of the aggregate.
 250+
 251+ 6. Conveying Non-Source Forms.
 252+
 253+ You may convey a covered work in object code form under the terms
 254+of sections 4 and 5, provided that you also convey the
 255+machine-readable Corresponding Source under the terms of this License,
 256+in one of these ways:
 257+
 258+ a) Convey the object code in, or embodied in, a physical product
 259+ (including a physical distribution medium), accompanied by the
 260+ Corresponding Source fixed on a durable physical medium
 261+ customarily used for software interchange.
 262+
 263+ b) Convey the object code in, or embodied in, a physical product
 264+ (including a physical distribution medium), accompanied by a
 265+ written offer, valid for at least three years and valid for as
 266+ long as you offer spare parts or customer support for that product
 267+ model, to give anyone who possesses the object code either (1) a
 268+ copy of the Corresponding Source for all the software in the
 269+ product that is covered by this License, on a durable physical
 270+ medium customarily used for software interchange, for a price no
 271+ more than your reasonable cost of physically performing this
 272+ conveying of source, or (2) access to copy the
 273+ Corresponding Source from a network server at no charge.
 274+
 275+ c) Convey individual copies of the object code with a copy of the
 276+ written offer to provide the Corresponding Source. This
 277+ alternative is allowed only occasionally and noncommercially, and
 278+ only if you received the object code with such an offer, in accord
 279+ with subsection 6b.
 280+
 281+ d) Convey the object code by offering access from a designated
 282+ place (gratis or for a charge), and offer equivalent access to the
 283+ Corresponding Source in the same way through the same place at no
 284+ further charge. You need not require recipients to copy the
 285+ Corresponding Source along with the object code. If the place to
 286+ copy the object code is a network server, the Corresponding Source
 287+ may be on a different server (operated by you or a third party)
 288+ that supports equivalent copying facilities, provided you maintain
 289+ clear directions next to the object code saying where to find the
 290+ Corresponding Source. Regardless of what server hosts the
 291+ Corresponding Source, you remain obligated to ensure that it is
 292+ available for as long as needed to satisfy these requirements.
 293+
 294+ e) Convey the object code using peer-to-peer transmission, provided
 295+ you inform other peers where the object code and Corresponding
 296+ Source of the work are being offered to the general public at no
 297+ charge under subsection 6d.
 298+
 299+ A separable portion of the object code, whose source code is excluded
 300+from the Corresponding Source as a System Library, need not be
 301+included in conveying the object code work.
 302+
 303+ A "User Product" is either (1) a "consumer product", which means any
 304+tangible personal property which is normally used for personal, family,
 305+or household purposes, or (2) anything designed or sold for incorporation
 306+into a dwelling. In determining whether a product is a consumer product,
 307+doubtful cases shall be resolved in favor of coverage. For a particular
 308+product received by a particular user, "normally used" refers to a
 309+typical or common use of that class of product, regardless of the status
 310+of the particular user or of the way in which the particular user
 311+actually uses, or expects or is expected to use, the product. A product
 312+is a consumer product regardless of whether the product has substantial
 313+commercial, industrial or non-consumer uses, unless such uses represent
 314+the only significant mode of use of the product.
 315+
 316+ "Installation Information" for a User Product means any methods,
 317+procedures, authorization keys, or other information required to install
 318+and execute modified versions of a covered work in that User Product from
 319+a modified version of its Corresponding Source. The information must
 320+suffice to ensure that the continued functioning of the modified object
 321+code is in no case prevented or interfered with solely because
 322+modification has been made.
 323+
 324+ If you convey an object code work under this section in, or with, or
 325+specifically for use in, a User Product, and the conveying occurs as
 326+part of a transaction in which the right of possession and use of the
 327+User Product is transferred to the recipient in perpetuity or for a
 328+fixed term (regardless of how the transaction is characterized), the
 329+Corresponding Source conveyed under this section must be accompanied
 330+by the Installation Information. But this requirement does not apply
 331+if neither you nor any third party retains the ability to install
 332+modified object code on the User Product (for example, the work has
 333+been installed in ROM).
 334+
 335+ The requirement to provide Installation Information does not include a
 336+requirement to continue to provide support service, warranty, or updates
 337+for a work that has been modified or installed by the recipient, or for
 338+the User Product in which it has been modified or installed. Access to a
 339+network may be denied when the modification itself materially and
 340+adversely affects the operation of the network or violates the rules and
 341+protocols for communication across the network.
 342+
 343+ Corresponding Source conveyed, and Installation Information provided,
 344+in accord with this section must be in a format that is publicly
 345+documented (and with an implementation available to the public in
 346+source code form), and must require no special password or key for
 347+unpacking, reading or copying.
 348+
 349+ 7. Additional Terms.
 350+
 351+ "Additional permissions" are terms that supplement the terms of this
 352+License by making exceptions from one or more of its conditions.
 353+Additional permissions that are applicable to the entire Program shall
 354+be treated as though they were included in this License, to the extent
 355+that they are valid under applicable law. If additional permissions
 356+apply only to part of the Program, that part may be used separately
 357+under those permissions, but the entire Program remains governed by
 358+this License without regard to the additional permissions.
 359+
 360+ When you convey a copy of a covered work, you may at your option
 361+remove any additional permissions from that copy, or from any part of
 362+it. (Additional permissions may be written to require their own
 363+removal in certain cases when you modify the work.) You may place
 364+additional permissions on material, added by you to a covered work,
 365+for which you have or can give appropriate copyright permission.
 366+
 367+ Notwithstanding any other provision of this License, for material you
 368+add to a covered work, you may (if authorized by the copyright holders of
 369+that material) supplement the terms of this License with terms:
 370+
 371+ a) Disclaiming warranty or limiting liability differently from the
 372+ terms of sections 15 and 16 of this License; or
 373+
 374+ b) Requiring preservation of specified reasonable legal notices or
 375+ author attributions in that material or in the Appropriate Legal
 376+ Notices displayed by works containing it; or
 377+
 378+ c) Prohibiting misrepresentation of the origin of that material, or
 379+ requiring that modified versions of such material be marked in
 380+ reasonable ways as different from the original version; or
 381+
 382+ d) Limiting the use for publicity purposes of names of licensors or
 383+ authors of the material; or
 384+
 385+ e) Declining to grant rights under trademark law for use of some
 386+ trade names, trademarks, or service marks; or
 387+
 388+ f) Requiring indemnification of licensors and authors of that
 389+ material by anyone who conveys the material (or modified versions of
 390+ it) with contractual assumptions of liability to the recipient, for
 391+ any liability that these contractual assumptions directly impose on
 392+ those licensors and authors.
 393+
 394+ All other non-permissive additional terms are considered "further
 395+restrictions" within the meaning of section 10. If the Program as you
 396+received it, or any part of it, contains a notice stating that it is
 397+governed by this License along with a term that is a further
 398+restriction, you may remove that term. If a license document contains
 399+a further restriction but permits relicensing or conveying under this
 400+License, you may add to a covered work material governed by the terms
 401+of that license document, provided that the further restriction does
 402+not survive such relicensing or conveying.
 403+
 404+ If you add terms to a covered work in accord with this section, you
 405+must place, in the relevant source files, a statement of the
 406+additional terms that apply to those files, or a notice indicating
 407+where to find the applicable terms.
 408+
 409+ Additional terms, permissive or non-permissive, may be stated in the
 410+form of a separately written license, or stated as exceptions;
 411+the above requirements apply either way.
 412+
 413+ 8. Termination.
 414+
 415+ You may not propagate or modify a covered work except as expressly
 416+provided under this License. Any attempt otherwise to propagate or
 417+modify it is void, and will automatically terminate your rights under
 418+this License (including any patent licenses granted under the third
 419+paragraph of section 11).
 420+
 421+ However, if you cease all violation of this License, then your
 422+license from a particular copyright holder is reinstated (a)
 423+provisionally, unless and until the copyright holder explicitly and
 424+finally terminates your license, and (b) permanently, if the copyright
 425+holder fails to notify you of the violation by some reasonable means
 426+prior to 60 days after the cessation.
 427+
 428+ Moreover, your license from a particular copyright holder is
 429+reinstated permanently if the copyright holder notifies you of the
 430+violation by some reasonable means, this is the first time you have
 431+received notice of violation of this License (for any work) from that
 432+copyright holder, and you cure the violation prior to 30 days after
 433+your receipt of the notice.
 434+
 435+ Termination of your rights under this section does not terminate the
 436+licenses of parties who have received copies or rights from you under
 437+this License. If your rights have been terminated and not permanently
 438+reinstated, you do not qualify to receive new licenses for the same
 439+material under section 10.
 440+
 441+ 9. Acceptance Not Required for Having Copies.
 442+
 443+ You are not required to accept this License in order to receive or
 444+run a copy of the Program. Ancillary propagation of a covered work
 445+occurring solely as a consequence of using peer-to-peer transmission
 446+to receive a copy likewise does not require acceptance. However,
 447+nothing other than this License grants you permission to propagate or
 448+modify any covered work. These actions infringe copyright if you do
 449+not accept this License. Therefore, by modifying or propagating a
 450+covered work, you indicate your acceptance of this License to do so.
 451+
 452+ 10. Automatic Licensing of Downstream Recipients.
 453+
 454+ Each time you convey a covered work, the recipient automatically
 455+receives a license from the original licensors, to run, modify and
 456+propagate that work, subject to this License. You are not responsible
 457+for enforcing compliance by third parties with this License.
 458+
 459+ An "entity transaction" is a transaction transferring control of an
 460+organization, or substantially all assets of one, or subdividing an
 461+organization, or merging organizations. If propagation of a covered
 462+work results from an entity transaction, each party to that
 463+transaction who receives a copy of the work also receives whatever
 464+licenses to the work the party's predecessor in interest had or could
 465+give under the previous paragraph, plus a right to possession of the
 466+Corresponding Source of the work from the predecessor in interest, if
 467+the predecessor has it or can get it with reasonable efforts.
 468+
 469+ You may not impose any further restrictions on the exercise of the
 470+rights granted or affirmed under this License. For example, you may
 471+not impose a license fee, royalty, or other charge for exercise of
 472+rights granted under this License, and you may not initiate litigation
 473+(including a cross-claim or counterclaim in a lawsuit) alleging that
 474+any patent claim is infringed by making, using, selling, offering for
 475+sale, or importing the Program or any portion of it.
 476+
 477+ 11. Patents.
 478+
 479+ A "contributor" is a copyright holder who authorizes use under this
 480+License of the Program or a work on which the Program is based. The
 481+work thus licensed is called the contributor's "contributor version".
 482+
 483+ A contributor's "essential patent claims" are all patent claims
 484+owned or controlled by the contributor, whether already acquired or
 485+hereafter acquired, that would be infringed by some manner, permitted
 486+by this License, of making, using, or selling its contributor version,
 487+but do not include claims that would be infringed only as a
 488+consequence of further modification of the contributor version. For
 489+purposes of this definition, "control" includes the right to grant
 490+patent sublicenses in a manner consistent with the requirements of
 491+this License.
 492+
 493+ Each contributor grants you a non-exclusive, worldwide, royalty-free
 494+patent license under the contributor's essential patent claims, to
 495+make, use, sell, offer for sale, import and otherwise run, modify and
 496+propagate the contents of its contributor version.
 497+
 498+ In the following three paragraphs, a "patent license" is any express
 499+agreement or commitment, however denominated, not to enforce a patent
 500+(such as an express permission to practice a patent or covenant not to
 501+sue for patent infringement). To "grant" such a patent license to a
 502+party means to make such an agreement or commitment not to enforce a
 503+patent against the party.
 504+
 505+ If you convey a covered work, knowingly relying on a patent license,
 506+and the Corresponding Source of the work is not available for anyone
 507+to copy, free of charge and under the terms of this License, through a
 508+publicly available network server or other readily accessible means,
 509+then you must either (1) cause the Corresponding Source to be so
 510+available, or (2) arrange to deprive yourself of the benefit of the
 511+patent license for this particular work, or (3) arrange, in a manner
 512+consistent with the requirements of this License, to extend the patent
 513+license to downstream recipients. "Knowingly relying" means you have
 514+actual knowledge that, but for the patent license, your conveying the
 515+covered work in a country, or your recipient's use of the covered work
 516+in a country, would infringe one or more identifiable patents in that
 517+country that you have reason to believe are valid.
 518+
 519+ If, pursuant to or in connection with a single transaction or
 520+arrangement, you convey, or propagate by procuring conveyance of, a
 521+covered work, and grant a patent license to some of the parties
 522+receiving the covered work authorizing them to use, propagate, modify
 523+or convey a specific copy of the covered work, then the patent license
 524+you grant is automatically extended to all recipients of the covered
 525+work and works based on it.
 526+
 527+ A patent license is "discriminatory" if it does not include within
 528+the scope of its coverage, prohibits the exercise of, or is
 529+conditioned on the non-exercise of one or more of the rights that are
 530+specifically granted under this License. You may not convey a covered
 531+work if you are a party to an arrangement with a third party that is
 532+in the business of distributing software, under which you make payment
 533+to the third party based on the extent of your activity of conveying
 534+the work, and under which the third party grants, to any of the
 535+parties who would receive the covered work from you, a discriminatory
 536+patent license (a) in connection with copies of the covered work
 537+conveyed by you (or copies made from those copies), or (b) primarily
 538+for and in connection with specific products or compilations that
 539+contain the covered work, unless you entered into that arrangement,
 540+or that patent license was granted, prior to 28 March 2007.
 541+
 542+ Nothing in this License shall be construed as excluding or limiting
 543+any implied license or other defenses to infringement that may
 544+otherwise be available to you under applicable patent law.
 545+
 546+ 12. No Surrender of Others' Freedom.
 547+
 548+ If conditions are imposed on you (whether by court order, agreement or
 549+otherwise) that contradict the conditions of this License, they do not
 550+excuse you from the conditions of this License. If you cannot convey a
 551+covered work so as to satisfy simultaneously your obligations under this
 552+License and any other pertinent obligations, then as a consequence you may
 553+not convey it at all. For example, if you agree to terms that obligate you
 554+to collect a royalty for further conveying from those to whom you convey
 555+the Program, the only way you could satisfy both those terms and this
 556+License would be to refrain entirely from conveying the Program.
 557+
 558+ 13. Use with the GNU Affero General Public License.
 559+
 560+ Notwithstanding any other provision of this License, you have
 561+permission to link or combine any covered work with a work licensed
 562+under version 3 of the GNU Affero General Public License into a single
 563+combined work, and to convey the resulting work. The terms of this
 564+License will continue to apply to the part which is the covered work,
 565+but the special requirements of the GNU Affero General Public License,
 566+section 13, concerning interaction through a network will apply to the
 567+combination as such.
 568+
 569+ 14. Revised Versions of this License.
 570+
 571+ The Free Software Foundation may publish revised and/or new versions of
 572+the GNU General Public License from time to time. Such new versions will
 573+be similar in spirit to the present version, but may differ in detail to
 574+address new problems or concerns.
 575+
 576+ Each version is given a distinguishing version number. If the
 577+Program specifies that a certain numbered version of the GNU General
 578+Public License "or any later version" applies to it, you have the
 579+option of following the terms and conditions either of that numbered
 580+version or of any later version published by the Free Software
 581+Foundation. If the Program does not specify a version number of the
 582+GNU General Public License, you may choose any version ever published
 583+by the Free Software Foundation.
 584+
 585+ If the Program specifies that a proxy can decide which future
 586+versions of the GNU General Public License can be used, that proxy's
 587+public statement of acceptance of a version permanently authorizes you
 588+to choose that version for the Program.
 589+
 590+ Later license versions may give you additional or different
 591+permissions. However, no additional obligations are imposed on any
 592+author or copyright holder as a result of your choosing to follow a
 593+later version.
 594+
 595+ 15. Disclaimer of Warranty.
 596+
 597+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
 598+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
 599+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
 600+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
 601+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 602+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
 603+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
 604+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 605+
 606+ 16. Limitation of Liability.
 607+
 608+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 609+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
 610+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
 611+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
 612+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
 613+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
 614+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
 615+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
 616+SUCH DAMAGES.
 617+
 618+ 17. Interpretation of Sections 15 and 16.
 619+
 620+ If the disclaimer of warranty and limitation of liability provided
 621+above cannot be given local legal effect according to their terms,
 622+reviewing courts shall apply local law that most closely approximates
 623+an absolute waiver of all civil liability in connection with the
 624+Program, unless a warranty or assumption of liability accompanies a
 625+copy of the Program in return for a fee.
 626+
 627+ END OF TERMS AND CONDITIONS
 628+
 629+ How to Apply These Terms to Your New Programs
 630+
 631+ If you develop a new program, and you want it to be of the greatest
 632+possible use to the public, the best way to achieve this is to make it
 633+free software which everyone can redistribute and change under these terms.
 634+
 635+ To do so, attach the following notices to the program. It is safest
 636+to attach them to the start of each source file to most effectively
 637+state the exclusion of warranty; and each file should have at least
 638+the "copyright" line and a pointer to where the full notice is found.
 639+
 640+ <one line to give the program's name and a brief idea of what it does.>
 641+ Copyright (C) <year> <name of author>
 642+
 643+ This program is free software: you can redistribute it and/or modify
 644+ it under the terms of the GNU General Public License as published by
 645+ the Free Software Foundation, either version 3 of the License, or
 646+ (at your option) any later version.
 647+
 648+ This program is distributed in the hope that it will be useful,
 649+ but WITHOUT ANY WARRANTY; without even the implied warranty of
 650+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 651+ GNU General Public License for more details.
 652+
 653+ You should have received a copy of the GNU General Public License
 654+ along with this program. If not, see <http://www.gnu.org/licenses/>.
 655+
 656+Also add information on how to contact you by electronic and paper mail.
 657+
 658+ If the program does terminal interaction, make it output a short
 659+notice like this when it starts in an interactive mode:
 660+
 661+ <program> Copyright (C) <year> <name of author>
 662+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 663+ This is free software, and you are welcome to redistribute it
 664+ under certain conditions; type `show c' for details.
 665+
 666+The hypothetical commands `show w' and `show c' should show the appropriate
 667+parts of the General Public License. Of course, your program's commands
 668+might be different; for a GUI interface, you would use an "about box".
 669+
 670+ You should also get your employer (if you work as a programmer) or school,
 671+if any, to sign a "copyright disclaimer" for the program, if necessary.
 672+For more information on this, and how to apply and follow the GNU GPL, see
 673+<http://www.gnu.org/licenses/>.
 674+
 675+ The GNU General Public License does not permit incorporating your program
 676+into proprietary programs. If your program is a subroutine library, you
 677+may consider it more useful to permit linking proprietary applications with
 678+the library. If this is what you want to do, use the GNU Lesser General
 679+Public License instead of this License. But first, please read
 680+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ShortQueryHover.initialize.js
@@ -0,0 +1,77 @@
 2+/**
 3+ * JavasSript for context popup initialization of the 'Semantic Expresiveness' extension.
 4+ * @see https://www.mediawiki.org/wiki/Extension:Semantic_Expressiveness
 5+ *
 6+ * @since 0.1
 7+ * @ingroup Semantic Expresiveness
 8+ *
 9+ * @licence GNU GPL v3+
 10+ * @author Daniel Werner < danweetz at web dot de >
 11+ */
 12+
 13+/**
 14+ * Adds ui popup functionality to all short query results within a specified range of the document.
 15+ * In case the popup would refer to the same page as it is positioned on, it will only show basic
 16+ * information about the short query instead of loading its own content. In that case also the
 17+ * pastCfgFunc callback won't be called and the popups instance is a TitledContextPopup instead of
 18+ * a ShortQueryHover.
 19+ * @param range jQuery if not set, initialization will be done for the whole document.
 20+ * @param preCfgFunc Function callback which will be called before initialization. The uninitialized
 21+ * semanticExpresiveness.ui.ShortQueryHover will be passed as first argument.
 22+ * @param pastCfgFunc Function callback which will be called after each successful initialization. The
 23+ * newly created semanticExpresiveness.ui.ShortQueryHover will be passed as first argument.
 24+ */
 25+window.semanticExpresiveness.ui.ShortQueryHover.initialize = function( range, preCfgFunc, pastCfgFunc ) {
 26+ if( typeof range == 'undefined' ) {
 27+ range = $( 'body' );
 28+ }
 29+ if( typeof preCfgFunc == 'undefined' ) {
 30+ configFunc = function(){};
 31+ }
 32+ if( typeof pastCfgFunc == 'undefined' ) {
 33+ pastCfgFunc = function(){};
 34+ }
 35+ range
 36+ .find( 'span.shortQuery' )
 37+ .each( function() {
 38+ // create popup but don't initialize yet by not passing any arguments
 39+ var queryHover = new window.semanticExpresiveness.ui.ShortQueryHover();
 40+
 41+ // run callback for advanced configuration
 42+ preCfgFunc( queryHover );
 43+
 44+ try {
 45+ // in case the short query markup is invalid, initialization will trigger an error!
 46+ $sqResult = new window.semanticExpresiveness.ShortQueryResult( this );
 47+
 48+ if( $sqResult.isAbstractResult() ) {
 49+ return; // no popup for abstract (failed) queries
 50+ }
 51+ }
 52+ catch( e ) {
 53+ // initialize some simple context popup which at least communicates that this is
 54+ // some kind of invalid short query result
 55+ var errorHover = new window.semanticExpresiveness.ui.TitledContextPopup( this );
 56+ errorHover.setTitle(
 57+ $( '<strong class="semex-invalid-shortquery-format"/>' )
 58+ .text( 'Invalid short query format!' )
 59+ );
 60+ errorHover.setContent( null );
 61+ $( this ).addClass( 'semex-invalid-shortquery-format' );
 62+
 63+ return;
 64+ }
 65+
 66+ // init context popup after options are set
 67+ queryHover._init( $sqResult );
 68+
 69+ if( queryHover.getQueryResult().getSource() === window.wgTitle ) {
 70+ // first-level popup to the same page as it is placed on should only display the basic
 71+ // short query information instead of getting its own pages content via AJAX.
 72+ queryHover = queryHover.initializeSimilarTitledPopup();
 73+ }
 74+ else {
 75+ pastCfgFunc( queryHover );
 76+ }
 77+ } );
 78+};
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ShortQueryHover.initialize.js
___________________________________________________________________
Added: svn:eol-style
179 + native
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ShortQueryHover.js
@@ -0,0 +1,281 @@
 2+/**
 3+ * JavasSript for context popup of the 'Semantic Expresiveness' extension.
 4+ * @see https://www.mediawiki.org/wiki/Extension:Semantic_Expressiveness
 5+ *
 6+ * @since 0.1
 7+ * @ingroup Semantic Expresiveness
 8+ *
 9+ * @licence GNU GPL v3+
 10+ * @author Daniel Werner < danweetz at web dot de >
 11+ */
 12+
 13+/**
 14+ * Constructor for context Popup container adjusted for 'Semantic Expressiveness' extension needs
 15+ *
 16+ * @param subject semanticExpresiveness.ShortQueryResult
 17+ */
 18+window.semanticExpresiveness.ui.ShortQueryHover = function( subject ) {
 19+ window.semanticExpresiveness.ui.TitledContextPopup.call( this, subject );
 20+};
 21+
 22+/*
 23+ * Inherit and overwrite base class members:
 24+ */
 25+window.semanticExpresiveness.ui.ShortQueryHover.prototype = new window.semanticExpresiveness.ui.TitledContextPopup();
 26+$.extend( window.semanticExpresiveness.ui.ShortQueryHover.prototype, {
 27+
 28+ constructor: window.semanticExpresiveness.ui.ShortQueryHover,
 29+
 30+ // overwrite original content:
 31+ _content: $(
 32+ '<div class="semex-shortqueryinfo-loading">' +
 33+ mw.msg( 'semex-shortquery-hover-loading' ) + '...' +
 34+ '</div>'
 35+ ),
 36+
 37+ /**
 38+ * Associated short query result which belongs to the popups subject.
 39+ * @var: semanticExpresiveness.ShortQueryResult
 40+ */
 41+ _queryResult: null,
 42+
 43+ /**
 44+ * Whether the query information has been dynamically loaded or taken from cache (if in use).
 45+ * If that is the case, this._content contains the information.
 46+ * @var boolean
 47+ */
 48+ _queryInfoLoaded: false,
 49+
 50+ _init: function( subject ) {
 51+ if( ! ( subject instanceof window.semanticExpresiveness.ShortQueryResult ) ) {
 52+ throw new Error(
 53+ '"' + this.constructor +
 54+ '" initialization expects an instance of "ShortQueryResult" as first parameter.'
 55+ );
 56+ }
 57+ if( subject.isAbstractResult() ) {
 58+ throw new Error(
 59+ '"' + this.constructor + '" can not be built from an abstract "ShortQueryResult".'
 60+ );
 61+ }
 62+ this._queryResult = subject;
 63+
 64+ this.$package.TitledContextPopup.prototype._init.call( this, subject.getDOMNode() );
 65+ this._buildTitleInfo();
 66+ },
 67+
 68+ /**
 69+ * @see semanticExpresiveness.ui.TitledContextPopup._draw_buildPopup()
 70+ */
 71+ _draw_buildPopup: function() {
 72+ // call parent function...
 73+ divPopup = this.$package.TitledContextPopup.prototype._draw_buildPopup.call( this );
 74+ // add class to identify this as short query hover popup
 75+ divPopup.addClass( this.POPUP_CLASS + '-shortqueryhover' );
 76+
 77+ return divPopup;
 78+ },
 79+
 80+ /**
 81+ * destroys the short query hover popup and creates and initializes a simple TitledContextPopup
 82+ * with basic information about the short query target and without AJAX functionality instead.
 83+ * The new popup will be returned.
 84+ * @return semanticExpresiveness.ui.TitledContextPopup
 85+ */
 86+ initializeSimilarTitledPopup: function() {
 87+ var oldTitle = this.getTitle().clone();
 88+ var subject = this.getSubject().get( 0 );
 89+ this.destroy(); // destroy old popup before initializing any new one!
 90+
 91+ // create new popup with same values but with title only:
 92+ var newPopup = new window.semanticExpresiveness.ui.TitledContextPopup( subject );
 93+ newPopup.setTitle( oldTitle );
 94+ newPopup.setContent( null );
 95+
 96+ return newPopup;
 97+ },
 98+
 99+ /**
 100+ * Generates the information displayed as title
 101+ */
 102+ _buildTitleInfo: function() {
 103+ var sq = this._queryResult;
 104+
 105+ var prop = sq.getProperty();
 106+ prop = '<a href="' + mw.util.wikiGetlink( 'Property:' + prop ) + '">' + prop + '</a>';
 107+
 108+ var source = sq.getSource();
 109+ source = '<a href="' + mw.util.wikiGetlink( source ) + '">' + source + '</a>';
 110+
 111+ // put links into the message:
 112+ this.setTitle(
 113+ $( mw.msg( 'semex-shortquery-title', prop, source ) )
 114+ );
 115+ },
 116+
 117+ /**
 118+ * @see window.semanticExpresiveness.ui.ContextPopup.setContent()
 119+ */
 120+ setContent: function( content ) {
 121+ // Initialize short query popups within inserted code:
 122+ if( this.recursiveInitialization
 123+ && content instanceof jQuery // could be null or string as well!
 124+ ) {
 125+ this._doRecursiveInitialization( content );
 126+ }
 127+ this.$package.TitledContextPopup.prototype.setContent.call( this, content )
 128+ },
 129+
 130+ /**
 131+ * @see window.semanticExpresiveness.ui.ContextPopup.show()
 132+ */
 133+ show: function() {
 134+ if( ! this.$package.TitledContextPopup.prototype.show.call( this ) ) {
 135+ // no state change, do nothing
 136+ return false;
 137+ }
 138+
 139+ if( this.queryInfoCache && this.queryInfoCache.hasInfo( this ) ) {
 140+ // use cache
 141+ this._queryInfoLoaded = true;
 142+ // clone original information so recursively displaying same information won't do crazy things
 143+ this.setContent( this.queryInfoCache.getInfo( this ).clone() );
 144+ }
 145+ else {
 146+ // load information
 147+ this._loadQueryInfo();
 148+ }
 149+ return true;
 150+ },
 151+
 152+ /**
 153+ * Returns the link from where the popup should get its information.
 154+ * @return string
 155+ */
 156+ getQueryInfoSource: function() {
 157+ var source = this._queryResult.getSource();
 158+ return mw.util.wikiGetlink( source ) + '&action=render&action=purge';
 159+ },
 160+
 161+ /**
 162+ * Requests and extracts the information from the short query results source page.
 163+ */
 164+ _loadQueryInfo: function() {
 165+ var self = this;
 166+ var dummy = $( '<div/>' );
 167+
 168+ var request = this.getQueryInfoSource();
 169+ request += ' ' + this.queryInfoSelector;
 170+
 171+ dummy.load(
 172+ request,
 173+ function( rawData, status, jqXHR ) {
 174+ if( jqXHR.status == 0 ) {
 175+ dummy = false;
 176+ }
 177+ self._applyQueryInfo( dummy, rawData, jqXHR );
 178+ }
 179+ );
 180+ },
 181+
 182+ /**
 183+ * Applies the retrieved short query information.
 184+ * Also handles the caching and callback handling.
 185+ */
 186+ _applyQueryInfo: function( data, rawData, jqXHR ) {
 187+ if( this.beforeApplyQueryInfo !== null ) {
 188+ data = this.beforeApplyQueryInfo( data )
 189+ }
 190+ if( data === false ) {
 191+ /** @ToDo: right now the message gets treated as if it were the right value, might be
 192+ * of interest to notify the cache that this information is just a message
 193+ */
 194+ data = $(
 195+ '<div class="semex-shortqueryinfo-loading-failed">' +
 196+ mw.msg( 'semex-shortquery-hover-loading-failed' ) + '</div>'
 197+ );
 198+ }
 199+
 200+ // cache information if enabled:
 201+ if( this.queryInfoCache ) {
 202+ this.queryInfoCache.addInfo( this, data );
 203+ }
 204+ // apply new content:
 205+ this._queryInfoLoaded = true;
 206+ this.setContent( data.clone() );
 207+ },
 208+
 209+ /**
 210+ * Checks new popup content for further short queries and initializes their ui functionality.
 211+ * @param content jQuery
 212+ */
 213+ _doRecursiveInitialization: function( content ) {
 214+ var self = this;
 215+ this.$package.ShortQueryHover.initialize(
 216+ content,
 217+ function( queryHover ) { // configuration per ShortQueryHover element
 218+ queryHover.queryInfoCache = self.queryInfoCache;
 219+ queryHover.queryInfoSelector = self.queryInfoSelector;
 220+ queryHover.recursiveInitialization = true;
 221+ },
 222+ function( queryHover ) {
 223+ if( self.getQueryResult().getSource() !== queryHover.getQueryResult().getSource() ) {
 224+ return queryHover;
 225+ }
 226+ // this popups content would be the same as the parent popups content, so display
 227+ // necessary information only to avoid endless chains of the same popup
 228+ queryHover = queryHover.initializeSimilarTitledPopup();
 229+ }
 230+ );
 231+ },
 232+
 233+ /**
 234+ * Returns the associated Querry Result object
 235+ * @returns semanticExpresiveness.ShortQueryResult
 236+ */
 237+ getQueryResult: function() {
 238+ return this._queryResult;
 239+ },
 240+
 241+ ///////////
 242+ // EVENTS:
 243+ ///////////
 244+
 245+ /**
 246+ * Callback called once after the information from the short queries source page has been loaded,
 247+ * just before the information will be set as the context popups content. The return value of the
 248+ * callback allows to return a modified jQuery object which will be set as the popups content then.
 249+ * If false is returned, it indicates that no information was found.
 250+ * @param data jQuery|false the original extracted information from the short queries target page.
 251+ * If set to false, this implies that loading the information has failed.
 252+ * @return jQuery|false
 253+ */
 254+ beforeApplyQueryInfo: null,
 255+
 256+ /////////////////
 257+ // CONFIGURABLE:
 258+ /////////////////
 259+
 260+ /**
 261+ * If set to false, there is no cache and each displaying of a short query popup will lead to loading
 262+ * the required information again. If set to an Cache object, the information will be stored within.
 263+ * This allows a global cache to share information once retrieved between short queries which have the
 264+ * same target page.
 265+ * @var false|semanticExpresiveness.ui.ShortQueryHover.Cache
 266+ */
 267+ queryInfoCache: false,
 268+
 269+ /**
 270+ * A valid jQuery selector to choose which elements from the short query target page should be
 271+ * selected as popup content.
 272+ * @var string
 273+ */
 274+ queryInfoSelector: '.NavFrame, .freeInfoBox',
 275+
 276+ /**
 277+ * If set to true, any content displayed within the popup will be checked for further short queries which
 278+ * will then be initialized as well.
 279+ * @var boolean
 280+ */
 281+ recursiveInitialization: true
 282+} );
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ShortQueryHover.js
___________________________________________________________________
Added: svn:eol-style
1283 + native
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.TitledContextPopup.css
@@ -0,0 +1,30 @@
 2+#ui-titledcontextpopup-store { position: absolute; top: 0; left: 0; margin: 0; padding: 0; }
 3+
 4+.ui-contextpopup-titlepopup-title {
 5+ background-color: #f2f2f2;
 6+ border: none;
 7+ padding: 4px;
 8+ font-weight: bold;
 9+}
 10+
 11+.ui-contextpopup-titlepopup-container {
 12+ padding: 0;
 13+}
 14+.ui-contextpopup-titlepopup-content {
 15+ padding: 2px;
 16+}
 17+
 18+.ui-contextpopup-onbottom .ui-contextpopup-titlepopup-content {
 19+ border-top: 1px solid #b8b8b8;
 20+}
 21+
 22+.ui-contextpopup-ontop .ui-contextpopup-titlepopup-content {
 23+ border-bottom: 1px solid #b8b8b8;
 24+}
 25+
 26+.ui-contextpopup-titlepopup .ui-contextpopup-pointer-onbottom {
 27+ background-image: url('./images/pointer-up-titledpopup.png');
 28+}
 29+.ui-contextpopup-titlepopup .ui-contextpopup-pointer-ontop {
 30+ background-image: url('./images/pointer-down-titledpopup.png');
 31+}
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.TitledContextPopup.css
___________________________________________________________________
Added: svn:eol-style
132 + native
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ShortQueryHover.Cache.js
@@ -0,0 +1,79 @@
 2+/**
 3+ * JavasSript for context popup of the 'Semantic Expresiveness' extension.
 4+ * @see https://www.mediawiki.org/wiki/Extension:Semantic_Expressiveness
 5+ *
 6+ * @since 0.1
 7+ * @ingroup Semantic Expresiveness
 8+ *
 9+ * @licence GNU GPL v3+
 10+ * @author Daniel Werner < danweetz at web dot de >
 11+ */
 12+
 13+/**
 14+ * Constructor for AJAX short query information cache which can be used to share retrieved
 15+ * information between several ShortQueryHover elements.
 16+ */
 17+window.semanticExpresiveness.ui.ShortQueryHover.Cache = function(){
 18+}
 19+
 20+window.semanticExpresiveness.ui.ShortQueryHover.Cache.prototype = {
 21+ /*
 22+ * Internal store for cached elements
 23+ */
 24+ _cache: new Object,
 25+
 26+ _resolveContext: function( context ) {
 27+ if( context instanceof String ) {
 28+ return context;
 29+ }
 30+ return context.getQueryResult().getSource();
 31+ },
 32+
 33+ /**
 34+ * Returns an information which has been cached before.
 35+ * @param context semanticExpresiveness.ui.ShortQueryHover|string
 36+ * @return mixed
 37+ */
 38+ getInfo: function( context ) {
 39+ return this._cache[ '__' + this._resolveContext( context ) ];
 40+ },
 41+
 42+ /*
 43+ * Cache something.
 44+ * @param context semanticExpresiveness.ui.ShortQueryHover|string
 45+ * @param value mixed information to cache
 46+ */
 47+ addInfo: function( context, value ) {
 48+ this._cache[ '__' + this._resolveContext( context ) ] = value;
 49+ },
 50+
 51+ /*
 52+ * Removes one information from the cache.
 53+ * @param context semanticExpresiveness.ui.ShortQueryHover|string
 54+ * @return boolean whether the information existed
 55+ */
 56+ removeInfo: function( context ) {
 57+ var key = this._resolveContext( context );
 58+ if( this.hasInfo( key ) ) {
 59+ delete this._cache[ '__' + key ];
 60+ return true;
 61+ }
 62+ return false;
 63+ },
 64+
 65+ /*
 66+ * Returns whether the information is cached already.
 67+ * @param context semanticExpresiveness.ui.ShortQueryHover|string
 68+ * @return boolean
 69+ */
 70+ hasInfo: function( context ) {
 71+ return this._cache.hasOwnProperty( '__' + this._resolveContext( context ) )
 72+ },
 73+
 74+ /*
 75+ * Removes all cached informations from the cache.
 76+ */
 77+ clear: function() {
 78+ this._cache = new Object();
 79+ }
 80+};
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ShortQueryHover.Cache.js
___________________________________________________________________
Added: svn:eol-style
181 + native
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.TitledContextPopup.js
@@ -0,0 +1,133 @@
 2+/**
 3+ * JavasSript for context popup of the 'Semantic Expresiveness' extension.
 4+ * @see https://www.mediawiki.org/wiki/Extension:Semantic_Expressiveness
 5+ *
 6+ * @since 0.1
 7+ * @ingroup Semantic Expresiveness
 8+ *
 9+ * @licence GNU GPL v3+
 10+ * @author Daniel Werner < danweetz at web dot de >
 11+ */
 12+
 13+/**
 14+ * Constructor for context popup container which allows to display some title section
 15+ * next to the subject but within the context popup box. This means if the popup gets
 16+ * displayed above its triggering subject, the title will be displayed at the popups
 17+ * bottom, if the popup will be beyond the subject, the title will be displayed on top.
 18+ */
 19+window.semanticExpresiveness.ui.TitledContextPopup = function( subject ){
 20+ window.semanticExpresiveness.ui.ContextPopup.call( this, subject );
 21+};
 22+
 23+/*
 24+ * Inherit and overwrite base class members:
 25+ */
 26+window.semanticExpresiveness.ui.TitledContextPopup.prototype = new window.semanticExpresiveness.ui.ContextPopup();
 27+$.extend( window.semanticExpresiveness.ui.TitledContextPopup.prototype, {
 28+
 29+ /**
 30+ * Title which should be displayed next to the popups content.
 31+ * @var jQuery
 32+ */
 33+ _title: null,
 34+
 35+ /**
 36+ * @see semanticExpresiveness.ui.TitledContextPopup.POPUP_STORE_ID
 37+ */
 38+ //POPUP_STORE_ID: 'ui-titledcontextpopup-store',
 39+
 40+ /**
 41+ * Allows to set the content of the title.
 42+ * @param $content jQuery|String
 43+ */
 44+ setTitle: function( content ) {
 45+ if( typeof content == 'undefined' ) {
 46+ content = null
 47+ }
 48+ if( content instanceof String ) {
 49+ content = $( document.createTextNode( content ) );
 50+ }
 51+ this._title = content;
 52+ },
 53+
 54+ /**
 55+ * Returns the content which should be displayed as title within the popup container.
 56+ * @return jQuery
 57+ */
 58+ getTitle: function() {
 59+ return this._title;
 60+ },
 61+
 62+ /**
 63+ * @see semanticExpresiveness.ui.ContextPopup._draw_buildPopup()
 64+ */
 65+ _draw_buildPopup: function() {
 66+ // call parent function...
 67+ divPopup = this.$package.ContextPopup.prototype._draw_buildPopup.call( this );
 68+
 69+ if( this._title === null ) {
 70+ // TitleContextPopup without title set is not much more than normal ContextPopup
 71+ return divPopup;
 72+ }
 73+
 74+ var boxClass = this.POPUP_CLASS + '-box';
 75+
 76+ // ...to get the content part from DOM
 77+ divContent = divPopup.children( '.' + boxClass );
 78+ divContent
 79+ .addClass( this.POPUP_CLASS + '-titlepopup-content' )
 80+ .removeClass( boxClass );
 81+
 82+ var divContainer = $( '<div/>', { // parent for title and content, replaces old content node
 83+ 'class': this.POPUP_CLASS + '-titlepopup-container ' + boxClass
 84+ } );
 85+ var divTitle = $( '<div/>', { // title, next to content node
 86+ 'class': this.POPUP_CLASS + '-titlepopup-title'
 87+ } );
 88+ divTitle.append( this._title );
 89+
 90+ // set content div next to title div within a new container:
 91+ divContainer.append( divTitle );
 92+ if( this._content !== null ) {
 93+ divContainer.append( divContent );
 94+ } else {
 95+ // Title popup can have empty content (if title is set)
 96+ divContent.empty().remove();
 97+ }
 98+ divPopup
 99+ .append( divContainer )
 100+ .addClass( this.POPUP_CLASS + '-titlepopup' );
 101+
 102+ return divPopup;
 103+ },
 104+
 105+ /**
 106+ * @see semanticExpresiveness.ui.TitledContextPopup._draw_doPositioning()
 107+ */
 108+ _draw_doPositioning: function() {
 109+ // we have positioned the title on top before, check whether it should be at the bottom:
 110+ if( this.getTitlePosition() === this.ORIENTATION.BOTTOM ) {
 111+ // find titles div and put it at the end
 112+ var divTitle = this._popup.find( '.' + this.POPUP_CLASS + '-titlepopup-title' );
 113+ divTitle.parent().append( divTitle.detach() );
 114+ }
 115+ this.$package.ContextPopup.prototype._draw_doPositioning.call( this );
 116+ },
 117+
 118+ /**
 119+ * Returns the designated position of the title part of the popup. If the popup is not visible
 120+ * at the moment or no title is set, null will be returned.
 121+ * @return integer|null
 122+ */
 123+ getTitlePosition: function() {
 124+ if( this._orientation == null || this._title == null ) {
 125+ return null;
 126+ }
 127+ if( this._orientation.vertical == this.ORIENTATION.TOP ) {
 128+ return this.ORIENTATION.BOTTOM;
 129+ } else {
 130+ return this.ORIENTATION.TOP;
 131+ }
 132+ }
 133+
 134+} );
\ No newline at end of file
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.TitledContextPopup.js
___________________________________________________________________
Added: svn:eol-style
1135 + native
Index: trunk/extensions/SemanticExpressiveness/resources/images/pointer-down-titledpopup.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/SemanticExpressiveness/resources/images/pointer-down-titledpopup.png
___________________________________________________________________
Added: svn:mime-type
2136 + image/png
Index: trunk/extensions/SemanticExpressiveness/resources/images/pointer-up.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/SemanticExpressiveness/resources/images/pointer-up.png
___________________________________________________________________
Added: svn:mime-type
3137 + image/png
Index: trunk/extensions/SemanticExpressiveness/resources/images/pointer.psd
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/SemanticExpressiveness/resources/images/pointer.psd
___________________________________________________________________
Added: svn:mime-type
4138 + application/octet-stream
Index: trunk/extensions/SemanticExpressiveness/resources/images/pointer-down.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/SemanticExpressiveness/resources/images/pointer-down.png
___________________________________________________________________
Added: svn:mime-type
5139 + image/png
Index: trunk/extensions/SemanticExpressiveness/resources/images/pointer-up-titledpopup.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/SemanticExpressiveness/resources/images/pointer-up-titledpopup.png
___________________________________________________________________
Added: svn:mime-type
6140 + image/png
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.css
@@ -0,0 +1,29 @@
 2+.shortQuery .result {
 3+ border-bottom: 1px dotted grey;
 4+}
 5+.shortQuery > .source,
 6+.shortQuery > .type,
 7+.shortQuery > .value {
 8+ display: none;
 9+}
 10+
 11+.abstractShortQueryValue {
 12+ font-style: italic!important;
 13+ background-color: rgba( 235, 90, 90, 0.1 );
 14+ border: 1px solid rgba( 235, 90, 90, 0.1 );
 15+}
 16+.abstractShortQueryValue * {
 17+ font-style: normal;
 18+}
 19+.abstractShortQueryValue .result {
 20+ background-color: #edf9d8;
 21+ border-top: 1px solid #dff0bf;
 22+ padding: 0 2px;
 23+ margin-left: -2px;
 24+}
 25+
 26+.abstractShortQuery .property a:not( :hover ):not( .new ) {
 27+ /* don't show link color if property exists, but show it on :hover */
 28+ color: inherit;
 29+ text-decoration: underline;
 30+}
\ No newline at end of file
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.css
___________________________________________________________________
Added: svn:eol-style
131 + native
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.js
@@ -0,0 +1,15 @@
 2+/**
 3+ * JavasSript for context popup of the 'Semantic Expresiveness' extension.
 4+ * @see https://www.mediawiki.org/wiki/Extension:Semantic_Expressiveness
 5+ *
 6+ * @since 0.1
 7+ * @ingroup Semantic Expresiveness
 8+ *
 9+ * @licence GNU GPL v3+
 10+ * @author Daniel Werner < danweetz at web dot de >
 11+ */
 12+
 13+/**
 14+ * Module for 'Semantic Expresiveness' extensions user interface elements.
 15+ */
 16+window.semanticExpresiveness.ui = {};
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.js
___________________________________________________________________
Added: svn:eol-style
117 + native
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.InlineMeasurer.js
@@ -0,0 +1,84 @@
 2+/**
 3+ * JavasSript to measure some multi-line inline element.
 4+ * @see https://www.mediawiki.org/wiki/Extension:Semantic_Expressiveness
 5+ *
 6+ * @since 0.1
 7+ * @ingroup Semantic Expresiveness
 8+ *
 9+ * @licence GNU GPL v3+
 10+ * @author Daniel Werner < danweetz at web dot de >
 11+ */
 12+
 13+/**
 14+ * The InlineMeasurer helps to get some information about multi-line inline elements,
 15+ * like where does the element start in the first line, where does it end in the last
 16+ * line and how many lines does it have.
 17+ */
 18+window.semanticExpresiveness.ui.InlineMeasurer = {};
 19+
 20+/**
 21+ * Function to meassure some inline element. The function has to temporarily modify the
 22+ * element and add some <span/> at its beginning and end.
 23+ * @returns semanticExpresiveness.ui.InlineMeasurer.Measurement
 24+ *
 25+ * @ToDo: Add support and test this for right-to-left languages
 26+ *
 27+ * Note: This would be possible with getClientRects() as well. But it has poor browser
 28+ * support (IE6+7 zoom behavior).
 29+ */
 30+window.semanticExpresiveness.ui.InlineMeasurer.measure = function( element ) {
 31+ var elem = $( element );
 32+ var result = new window.semanticExpresiveness.ui.InlineMeasurer.Measurement( element );
 33+
 34+ // add helpers into dom:
 35+ var helper1 = $( '<span/>' );
 36+ var helper2 = $( '<span/>' );
 37+ elem.prepend( helper1 );
 38+ elem.append( helper2 );
 39+
 40+ // measure:
 41+ result.isOneLiner = helper1.position().top === helper2.position().top;
 42+ result.firstLineWidth = elem.outerWidth() - ( helper1.offset().left - elem.offset().left );
 43+ result.lastLineOffset = helper2.offset().left - elem.offset().left;
 44+
 45+ // destroy helper objects:
 46+ helper1.empty().remove()
 47+ helper2.empty().remove()
 48+
 49+ return result;
 50+}
 51+
 52+/**
 53+ * Constructor for Object returned by measure() function.
 54+ */
 55+window.semanticExpresiveness.ui.InlineMeasurer.Measurement = function( element ) {
 56+ this.element = element;
 57+};
 58+window.semanticExpresiveness.ui.InlineMeasurer.Measurement.prototype = {
 59+ /**
 60+ * The element the other informations relate to. Be aware that the related informations
 61+ * could be 'wrong' due to some DOM updates or other influences already.
 62+ */
 63+ element: null,
 64+
 65+ /*
 66+ * Whether the inline-element spreads over several lines. This can change after text or DOM
 67+ * have been modified or even when re-sizing the browsers viewport.
 68+ * @var boolean
 69+ */
 70+ isOneLiner: true,
 71+
 72+ /**
 73+ * Width of the first line. In case the element spreads over several lines, the first and the
 74+ * last line could be shorter as the whole elements width.
 75+ * @var integer
 76+ */
 77+ firstLineWidth: 0,
 78+
 79+ /**
 80+ * Width of the last line. In case the element spreads over several lines, the first and the
 81+ * last line could be shorter as the whole elements width.
 82+ * @var integer
 83+ */
 84+ lastLineWidth: 0
 85+};
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.InlineMeasurer.js
___________________________________________________________________
Added: svn:eol-style
186 + native
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ContextPopup.css
@@ -0,0 +1,75 @@
 2+
 3+#ui-contextpopup-store { position: absolute; top: 0; left: 0; margin: 0; padding: 0; }
 4+
 5+/* The actual visible popup */
 6+.ui-contextpopup {
 7+ position: absolute;
 8+ z-index: 999;
 9+ padding: 0;
 10+}
 11+
 12+.ui-contextpopup-subject {
 13+}
 14+
 15+.ui-contextpopup-subject-active {
 16+ background-color: #f2f2f2;
 17+}
 18+
 19+.ui-contextpopup-ontop {
 20+ padding-bottom: 10px;
 21+}
 22+
 23+.ui-contextpopup-onbottom {
 24+ padding-top: 10px;
 25+}
 26+
 27+.ui-contextpopup-box {
 28+ box-shadow: 0px 3px 6px rgba(0,0,0,0.4);
 29+ -moz-box-shadow: 0px 3px 6px rgba(0,0,0,0.4);
 30+ -webkit-box-shadow: 0px 3px 6px rgba(0,0,0,0.4);
 31+ -khtml-box-shadow: 0px 3px 6px rgba(0,0,0,0.4);
 32+
 33+ border-radius: 2px;
 34+ -moz-border-radius: 2px;
 35+ -webkit-border-radius: 2px;
 36+ -khtml-border-radius: 2px;
 37+
 38+ background-color: white;
 39+ border: 1px #545454 solid;
 40+ padding: 4px;
 41+ height: auto;
 42+ width: auto;
 43+ min-width: 28px;
 44+ min-height: 4px;
 45+ z-index: auto;
 46+}
 47+
 48+.ui-contextpopup-pointer {
 49+ position:absolute;
 50+ height: 10px;
 51+ width: 20px;
 52+}
 53+
 54+.ui-contextpopup-pointer {
 55+ font-size:0px; /* for IE6 */
 56+ margin: 0;
 57+ padding: 0;
 58+}
 59+.ui-contextpopup-onbottom .ui-contextpopup-pointer {
 60+ background-image: url('./images/pointer-up.png');
 61+ top: 1px;
 62+}
 63+.ui-contextpopup-ontop .ui-contextpopup-pointer {
 64+ background-image: url('./images/pointer-down.png');
 65+ bottom: 1px;
 66+}
 67+.ui-contextpopup-fromright .ui-contextpopup-pointer {
 68+ left: 7px;
 69+}
 70+.ui-contextpopup-fromleft .ui-contextpopup-pointer {
 71+ right: 7px;
 72+}
 73+
 74+.ui-contextpopup .ui-contextpopup-box * {
 75+ float: none;
 76+}
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ContextPopup.css
___________________________________________________________________
Added: svn:eol-style
177 + native
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.js
@@ -0,0 +1,36 @@
 2+/**
 3+ * JavasSript for the 'Semantic Expresiveness' extension.
 4+ * @see https://www.mediawiki.org/wiki/Extension:Semantic_Expressiveness
 5+ *
 6+ * @since 0.1
 7+ * @ingroup Semantic Expresiveness
 8+ *
 9+ * @licence GNU GPL v3+
 10+ * @author Daniel Werner < danweetz at web dot de >
 11+ */
 12+window.semanticExpresiveness = new( function() {
 13+
 14+ this.log = function( message ) {
 15+ if( typeof mediaWiki === 'undefined' ) {
 16+ if( typeof console !== 'undefined' ) {
 17+ console.log( 'SemEx: ' + message );
 18+ }
 19+ }
 20+ else {
 21+ return mediaWiki.log.call( mediaWiki.log, 'SemEx: ' + message );
 22+ }
 23+ }
 24+
 25+ // Initialize user interface stuff when ready
 26+ jQuery( function( $ ) {
 27+ // add popup ui functionality to short query results:
 28+ var globalShortQueryInfoCache = new window.semanticExpresiveness.ui.ShortQueryHover.Cache;
 29+ window.semanticExpresiveness.ui.ShortQueryHover.initialize(
 30+ $( 'body' ),
 31+ function( queryHover ) { // configuration per ShortQueryHover element
 32+ queryHover.queryInfoCache = globalShortQueryInfoCache;
 33+ }
 34+ );
 35+ } );
 36+
 37+} )();
\ No newline at end of file
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.js
___________________________________________________________________
Added: svn:eol-style
138 + native
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ShortQueryHover.css
@@ -0,0 +1,29 @@
 2+/** @TODO: make this all configurable instead of using those two classes */
 3+.ui-contextpopup-shortqueryhover .freeInfoBox,
 4+.ui-contextpopup-shortqueryhover .NavFrame {
 5+ margin: 0;
 6+ border: none;
 7+ min-width: 300px;
 8+}
 9+
 10+.ui-contextpopup-shortqueryhover .ui-contextpopup-titlepopup-title {
 11+ font-weight: bold;
 12+ white-space: nowrap;
 13+}
 14+
 15+.ui-contextpopup .semex-invalid-shortquery-format {
 16+ color: red;
 17+}
 18+
 19+.ui-contextpopup-shortqueryhover .ui-contextpopup-titlepopup-content {
 20+ font-size: 0.82em;
 21+ font-family: verdana, sans-serif;
 22+}
 23+
 24+.semex-shortqueryinfo-loading,
 25+.semex-shortqueryinfo-loading-failed {
 26+ font-style: italic;
 27+}
 28+.semex-shortqueryinfo-loading-failed {
 29+ color: red;
 30+}
\ No newline at end of file
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ShortQueryHover.css
___________________________________________________________________
Added: svn:eol-style
131 + native
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ShortQueryResult.js
@@ -0,0 +1,145 @@
 2+/**
 3+ * JavasSript for representing some short query result
 4+ * @see https://www.mediawiki.org/wiki/Extension:Semantic_Expressiveness
 5+ *
 6+ * @since 0.1
 7+ * @ingroup Semantic Expresiveness
 8+ *
 9+ * @licence GNU GPL v3+
 10+ * @author Daniel Werner < danweetz at web dot de >
 11+ */
 12+
 13+/**
 14+ * Constructor for short query result representation within JavaScript.
 15+ * @param Node element representing the short Query.
 16+ * @throws Error in case the Short Query Result structure is invalid.
 17+ */
 18+window.semanticExpresiveness.ShortQueryResult = function( element ) {
 19+ this._elem = $( element );
 20+
 21+ // validation for the short query result:
 22+ if(
 23+ this.getSource() === false
 24+ || this.getProperty() === false
 25+ || this.isAbstractResult() === false
 26+ && ( this.getRawResult() === null || this.getResult() === null )
 27+ ) {
 28+ throw new Error( 'Invalid Short Query Result structure detected' );
 29+ }
 30+};
 31+window.semanticExpresiveness.ShortQueryResult.prototype = {
 32+ /**
 33+ * @var jQuery
 34+ */
 35+ _elem: null,
 36+ _querySource: null,
 37+ _queryProperty: null,
 38+ _queryRawResult: null,
 39+
 40+ /**
 41+ * Returns the node in the DOM representing this short query result.
 42+ * @return Node
 43+ */
 44+ getDOMNode: function() {
 45+ return this._elem;
 46+ },
 47+
 48+ /**
 49+ * Returns whether this short query result is an abstract result for some reason, most likely
 50+ * the query failed in this case.
 51+ * @return bool
 52+ */
 53+ isAbstractResult: function() {
 54+ return this._elem.hasClass( 'abstractShortQuery' );
 55+ },
 56+
 57+ /**
 58+ * Returns the local page name of the page the displayed query information was taken from.
 59+ * In case this is an abstract short query result, it is possible that the source was another
 60+ * unsuccessful short query. In this case, null will be returned.
 61+ * @return string|null
 62+ */
 63+ getSource: function() {
 64+ if( this._querySource !== null ) {
 65+ return this._querySource;
 66+ }
 67+ this._querySource = this._getShortQueryInfo( 'source' );
 68+
 69+ if( this._querySource === false
 70+ && this.isAbstractResult()
 71+ && this._elem.children( '.source' ).length == 1
 72+ ) {
 73+ // abstract result and another short query as source!
 74+ this._querySource = null;
 75+ }
 76+ return this._querySource;
 77+ },
 78+
 79+ /**
 80+ * Returns the property name of the queried value.
 81+ * @return string
 82+ */
 83+ getProperty: function() {
 84+ if( this._queryProperty !== null ) {
 85+ return this._queryProperty;
 86+ }
 87+ this._queryProperty = this._getShortQueryInfo( 'type' );
 88+ return this._queryProperty;
 89+ },
 90+
 91+ /**
 92+ * Returns the unformatted, raw result of the query. Returns null in case the query went wrong.
 93+ * @return string[]|null
 94+ */
 95+ getRawResult: function() {
 96+ if( this._queryRawResult !== null ) {
 97+ return this._queryRawResult;
 98+ }
 99+
 100+ // query result can have several values which are stored within the title of child elements
 101+ // of the short queries direct child with class 'value'
 102+ values = this._elem.children( '.value' ).children( '*[title]' );
 103+ if( values.length < 1 ) {
 104+ return null;
 105+ }
 106+
 107+ // put all values into an array:
 108+ var titles = new Array( values.length );
 109+
 110+ values.each( function( index, elem ) {
 111+ titles[index] = $( elem ).attr( 'title' )
 112+ } );
 113+
 114+ this._queryRawResult = titles;
 115+ return titles;
 116+ },
 117+
 118+ /**
 119+ * Returns the DOM elements which are part of the formatted result. Returns null in case the query
 120+ * went wrong. For unformatted result see getRawResult() function.
 121+ * @return jQuery|null
 122+ */
 123+ getResult: function() {
 124+ var result = this._elem.children( '.result' );
 125+ if( result.length != 1 ) {
 126+ return null
 127+ }
 128+ return result.contents();
 129+ },
 130+
 131+ /**
 132+ * Generic helper to get attached information from the short queries DOM.
 133+ * @param info string class name of the element where the information lays within the 'title'
 134+ */
 135+ _getShortQueryInfo: function( info ) {
 136+ var title = this._elem.children( '.' + info + '[title]' );
 137+ if( title.length != 1 ) {
 138+ return false;
 139+ }
 140+ title = $.trim( title.attr( 'title' ) );
 141+ if( title === '' ) {
 142+ return false;
 143+ }
 144+ return title;
 145+ }
 146+};
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ShortQueryResult.js
___________________________________________________________________
Added: svn:eol-style
1147 + native
Index: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ContextPopup.js
@@ -0,0 +1,810 @@
 2+/**
 3+ * JavasSript for context popup of the 'Semantic Expresiveness' extension.
 4+ * @see https://www.mediawiki.org/wiki/Extension:Semantic_Expressiveness
 5+ *
 6+ * @since 0.1
 7+ * @ingroup Semantic Expresiveness
 8+ *
 9+ * @licence GNU GPL v3+
 10+ * @author Daniel Werner < danweetz at web dot de >
 11+ */
 12+
 13+/**
 14+ * Constructor for context popup container which pops up whenever hovering over a defined
 15+ * inline-element.
 16+ * The context popups content can contain further popups. This works as long as the popups
 17+ * POPUP_CLASS and POPUP_STORE_ID are the same. Having several popups assigned to the same
 18+ * element or to sub-elements is very buggy and needs fixing if required for some reason.
 19+ *
 20+ * The Popups themselves are not part of the the subjects DOM. They are stored within a
 21+ * store for all popups. There were several reasons for this decission, adding the popup
 22+ * to the subjects DOM only worked until a certain point, it practically got too buggy.
 23+ *
 24+ * Known Bugs (all minor):
 25+ * =======================
 26+ * Opera/IE: Mouse-Events (mostly) don't get triggered for an element when the mouse didn't do
 27+ * anything but the element dynamically appears/disappeary under the mouse. This might
 28+ * lead to some bugs we don't have in Firefox.
 29+ *
 30+ * - Bug #101 (Opera/IE):
 31+ * When mouse leaves sub-popup, the popup fades out but the mouse goes right back in and then
 32+ * doesn't moove till some time after the sub-popup is completely gone, the parent popupS will
 33+ * close as well because the mouse event doesn't get triggered unline the mouse moves again!
 34+ * This can't just be solved by adding another event to the fading popup since then the mouse
 35+ * could go to space outside of parent popup without the parent being closed.
 36+ *
 37+ * - Bug #102 (Opera/IE):
 38+ * When content changes by using setContent() and the mouse is positioned within the popup and
 39+ * doesn't move untill the fade timer ran out, the popup will fade even though the mouse is
 40+ * positioned within. Event only gets triggered when mouse moves/clicks. window.scrollTo()
 41+ * workaround doesn't really work, it doesn't trigger any mouse event.
 42+ *
 43+ * @param subject Object the html dom element the context popup should be related to
 44+ */
 45+window.semanticExpresiveness.ui.ContextPopup = function( subject ) {
 46+ // alternative to any $parent or _super nonsens. At lest this save a few bytes of code
 47+ this.$package = window.semanticExpresiveness.ui;
 48+
 49+ // increase instances count to give IDs to popups
 50+ this._id = this.$package.ContextPopup.instances++;
 51+ this.POPUP_ID = this.POPUP_CLASS + '-' + this._id;
 52+
 53+ if( typeof subject != 'undefined' ) {
 54+ this._init( subject );
 55+ }
 56+};
 57+window.semanticExpresiveness.ui.ContextPopup.instances = 0;
 58+window.semanticExpresiveness.ui.ContextPopup.prototype = {
 59+ /**
 60+ * @const
 61+ * @enum number
 62+ */
 63+ PARTS: {
 64+ SUBJECT: 1,
 65+ POPUP: 2
 66+ },
 67+
 68+ /**
 69+ * @const
 70+ * @enum number
 71+ */
 72+ ORIENTATION: {
 73+ TOP: 1,
 74+ BOTTOM: 2,
 75+ LEFT: 3,
 76+ RIGHT: 4
 77+ },
 78+
 79+ TIME_TO_FIRST_NOTICE: 175, // time the mouse has to stay on the subject untill the popup fades in
 80+ TIME_TO_FADE_IN: 125,
 81+ TIME_TO_FADE_OUT: 150, // has to be lower than this.TIME_TO_REENTER time!
 82+ TIME_TO_REENTER: 333, // time after mouse has left popup untill the popup finally fades
 83+ // time after content-update to enter mouse to avoid bug #102 or in case popups position has changed:
 84+ TIME_TO_REENTER_ON_UPDATE: 1750,
 85+
 86+ /**
 87+ * @const
 88+ * Class which marks a popup within the site html.
 89+ */
 90+ POPUP_CLASS: 'ui-contextpopup',
 91+
 92+ /**
 93+ * @const
 94+ * ID of the popup which can be used within DOM or for events.
 95+ */
 96+ POPUP_ID: null, // POPUP_CLASS + _id (set by constructor)
 97+
 98+ /**
 99+ * @const
 100+ * ID to identify the popup store where the popups dom will temporarily be stored at.
 101+ */
 102+ POPUP_STORE_ID: 'ui-contextpopup-store',
 103+
 104+ /**
 105+ * Element the popup is related to.
 106+ * @var jQuery
 107+ */
 108+ _subject: null,
 109+
 110+ /**
 111+ * Content which should be displayed by the context popup.
 112+ * Set this from outside by using setContent()
 113+ * @var jQuery
 114+ */
 115+ _content: $( '<div style="font-style:italic;">No information available</div>' ),
 116+
 117+ /**
 118+ * Element which temporarily stores popup dom.
 119+ * @var jQuery|null
 120+ */
 121+ _popupStore: null,
 122+
 123+ /**
 124+ * An unique ID for the popup instance to keep track of its events.
 125+ * @var integer
 126+ */
 127+ _id: null,
 128+
 129+ /**
 130+ * Contains the popup in case it is visible currently.
 131+ * @var jQuery|null
 132+ */
 133+ _popup: null,
 134+
 135+ /**
 136+ * Whether the box is visible currently.
 137+ * @var boolean
 138+ */
 139+ _visible: false,
 140+
 141+ /**
 142+ * Contains the current orientation of the box. If it isn't visible at the moment this
 143+ * will be set to null.
 144+ * @var Object|null
 145+ */
 146+ _orientation: null,
 147+
 148+ /**
 149+ * Equals one of this.PARTS properties to give information about which part of the ui element
 150+ * was last and still is touched. In case the mouse is outside, this is set to null
 151+ * In case this.isTouchable is set to false, this won't be set to this.PARTS.POPUP
 152+ * @var integer|null
 153+ */
 154+ _touchedPart: null,
 155+
 156+ /**
 157+ * Initialize the context popup and assign it to some html element.
 158+ * This should normally be called directly by the constructor.
 159+ */
 160+ _init: function( subject ) {
 161+ if( this._subject !== null ) {
 162+ // initializing twice should never happen, have to destroy first!
 163+ this.destroy();
 164+ }
 165+ this._subject = $( subject );
 166+ this._subject.addClass( this.POPUP_CLASS + '-subject' );
 167+ // kind of bind this object to the element so parents can find their child context popups
 168+ this._subject.data( this.POPUP_CLASS, this );
 169+
 170+ // remove title so it won't get in the way of the popup
 171+ this._subject.data( this.POPUP_ID + '-origTitle', this._subject.attr( 'title' ) );
 172+ this._subject.removeAttr( 'title' );
 173+
 174+ // register events for associated popup trigger:
 175+ var self = this;
 176+ this._subject.bind(
 177+ 'mouseenter.' + this.POPUP_ID,
 178+ function() { self._hoverInFunc( self.PARTS.SUBJECT ) }
 179+ ).bind(
 180+ 'mouseleave.' + this.POPUP_ID,
 181+ function() { self._hoverOutFunc() }
 182+ );
 183+ },
 184+
 185+ /**
 186+ * Savely removes the popup and associated events from the DOM
 187+ */
 188+ destroy: function() {
 189+ if( this._id === null ) {
 190+ return;
 191+ }
 192+ this._subject
 193+ .unbind( '.' + this.POPUP_ID )
 194+ // restore original title which was removed before:
 195+ .attr( 'title', this._subject.data( this.POPUP_ID + '-origTitle' ) );
 196+
 197+ this._subject
 198+ .removeData( this.POPUP_ID + '-origTitle' )
 199+ .removeData( this.POPUP_CLASS )
 200+ .removeClass( this.POPUP_CLASS + '-subject' )
 201+ .removeClass( this.POPUP_CLASS + '-subject-active' );
 202+
 203+ if( this._popup !== null ) {
 204+ this._popup.empty().remove();
 205+ }
 206+ },
 207+
 208+ _hoverInFunc: function( part ) {
 209+ this._touchedPart = part;
 210+ // abord countdown to close()
 211+ this._clearTimeTillFade();
 212+
 213+ if( ! this.isVisible() ) {
 214+ // wait short time before opening popup, so fast mouse movments over document won't
 215+ // unintendedly trigger too many popups.
 216+ this._setTimeTillDisplay( this.TIME_TO_FIRST_NOTICE );
 217+ }
 218+ },
 219+ _hoverOutFunc: function() {
 220+ var lastTouched = this._touchedPart;
 221+ this._touchedPart = null;
 222+ if( ! this.isVisible() ) {
 223+ // abord countdown to show()
 224+ this._clearTimeTillDisplay();
 225+ }
 226+ else {
 227+ activeChild = this.getActiveChild();
 228+
 229+ if( lastTouched === this.PARTS.SUBJECT
 230+ && activeChild !== null
 231+ && activeChild._touchedPart !== null
 232+ ) {
 233+ // we entered, not left some sub-popup, so don't close anything!
 234+ return;
 235+ }
 236+
 237+ if( lastTouched !== this.PARTS.SUBJECT ) {
 238+ // consider closing all parents if mouse doesn't touch any in time
 239+ this._setTimeTillFadeParents( this.TIME_TO_REENTER );
 240+ } else {
 241+ // mouse entered parent popup since last touched part is the subject which has to be
 242+ // a part of the parent (if any parent popup exists)
 243+ this._setTimeTillFade( this.TIME_TO_REENTER );
 244+ }
 245+ }
 246+ },
 247+
 248+ /**
 249+ * Sets the time the mouse has to be somewhere where the popup gets triggered to actually display
 250+ * the popup.
 251+ * @param time integer
 252+ * @param callback Function executed after this.show() (optional)
 253+ */
 254+ _setTimeTillDisplay: function( time, callback ) {
 255+ var self = this;
 256+ var timeoutId = setTimeout( function(){
 257+ self.show();
 258+ if( typeof callback != 'undefined' ) {
 259+ callback();
 260+ }
 261+ }, time );
 262+ $( this ).data( this.POPUP_ID + '-enterTimeoutId', timeoutId );
 263+ },
 264+ _clearTimeTillDisplay: function() {
 265+ clearTimeout( $( this ).data( this.POPUP_ID + '-enterTimeoutId' ) );
 266+ },
 267+
 268+ /**
 269+ * Sets the time left untill the popup will be closed if the mouse doesn't re-activate it somehow.
 270+ * @param time integer
 271+ * @param callback Function executed after this.close() (optional)
 272+ */
 273+ _setTimeTillFade: function( time, callback ) {
 274+ var self = this;
 275+ var timeoutId = setTimeout( function(){
 276+ self.close();
 277+ if( typeof callback != 'undefined' ) {
 278+ callback();
 279+ }
 280+ }, time );
 281+ $( this ).data( this.POPUP_ID + '-fadeTimeoutId', timeoutId );
 282+ },
 283+ /**
 284+ * Same as _setTimeTillFade() but also does the same for all parent-popups.
 285+ * @param time integer
 286+ * @param callback Function exectued for each affected popup after this.close() (optional)
 287+ */
 288+ _setTimeTillFadeParents: function( time, callback ) {
 289+ // fade this popup first, then first parent all up the chain
 290+ this._setTimeTillFade( time, callback );
 291+ // do the same for all parents:
 292+ var parent = this.getParent();
 293+ if( parent !== null ){
 294+ parent._setTimeTillFadeParents( time, callback );
 295+ }
 296+ },
 297+ /**
 298+ * Cancels the timer till popup will fade. This also stops the timer for all parents since a
 299+ * popup can't exist without its parent.
 300+ */
 301+ _clearTimeTillFade: function() {
 302+ // do the same for all parents:
 303+ var parent = this.getParent();
 304+ if( parent !== null ){
 305+ parent._clearTimeTillFade();
 306+ }
 307+ // stop parent from fading first^^
 308+ clearTimeout( $( this ).data( this.POPUP_ID + '-fadeTimeoutId' ) );
 309+ },
 310+
 311+ /**
 312+ * Returns the element where the popup elements will temporarily be stored. If no store
 313+ * exists yet, this will create one.
 314+ * @return jQuery
 315+ */
 316+ getPopupStore: function() {
 317+ if( ! this._popupStore ) {
 318+ var store = $( '#' + this.POPUP_STORE_ID );
 319+ if( store.length == 0 ) {
 320+ // no store yet, create it
 321+ var store = $( '<div/>', {
 322+ 'id': this.POPUP_STORE_ID
 323+ }
 324+ );
 325+ store.appendTo( '#bodyContent' ); // place for MWs content, to have proper css for popups
 326+ }
 327+ this._popupStore = store;
 328+ }
 329+ return this._popupStore;
 330+ },
 331+
 332+ /**
 333+ * Returns the popups current orientation or null if its not displayed right now.
 334+ * @return integer|null
 335+ */
 336+ getOrientation: function() {
 337+ return this._orientation;
 338+ },
 339+
 340+ /**
 341+ * Function for (re)rendering the box at the ideal place, taking the boxes size and current
 342+ * position of the subject element relative to the current viewport in acount. If the box is not
 343+ * visible right now, this will not activate the box, use the show() function instead.
 344+ * @param orientation Object containing values from this.ORIENTATION for the properties 'horizontal'
 345+ * and 'vertical' if any specific orientation should be forced. (optional)
 346+ * @returns boolean whether any (re)drawing did happen.
 347+ */
 348+ draw: function( orientation ) {
 349+ if( ! this.isVisible ) {
 350+ // nothing to draw!
 351+ return false;
 352+ }
 353+
 354+ var isUpdate = this._popup !== null; // is this a update of the content while popup is visible?
 355+
 356+ // append popup here so css is taken into account for POSITIONING calculations
 357+ divPopup = this._draw_buildPopup();
 358+ if( isUpdate ) {
 359+ // detach popup so we can be 100% sure that the mouseenter event gets fired in case
 360+ // re-positioning doesn't change position and mouse is still within popup
 361+ divPopup.detach();
 362+ }
 363+ divPopup.appendTo( this.getPopupStore() );
 364+
 365+ if( typeof orientation == 'undefined' ) {
 366+ // calculate popup box positioning:
 367+ orientation = this.getIdealAlignment( divPopup );
 368+ }
 369+
 370+ this._popup = divPopup;
 371+ this._orientation = orientation;
 372+
 373+ // POSITIONING of the popup
 374+ this._draw_doPositioning();
 375+
 376+ if( isUpdate // if we update the popups content while it is still visible
 377+ && this._touchedPart != this.PARTS.SUBJECT // and mouse possibly within popup
 378+ ) {
 379+ // will be triggered even if mouse still within popup since we detached the popup before.
 380+ // in case the mouse is outside the new popup, this leaves us with enough time to enter the popup.
 381+ this._setTimeTillFadeParents( this.TIME_TO_REENTER_ON_UPDATE );
 382+ self._touchedPart = null; // parents should be set to null already
 383+ //this._draw_contentUpdateCleanup( divPopup, orientation );
 384+
 385+ // FIXME: no solution for Bug #102 yet. (window.scrollTo() no solution, doesn't trigger mouse event)
 386+ }
 387+
 388+ this._popup.hide().fadeIn( this.TIME_TO_FADE_IN );
 389+
 390+ return true;
 391+ },
 392+
 393+ /**
 394+ * Sub-routine of this.draw() to do the positioning so the popup will appear relative
 395+ * to the triggering subject element.
 396+ */
 397+ _draw_doPositioning: function() {
 398+ // Consider that the popup store might not be at position 0;0 !
 399+ var popupStoreOffset = this.getPopupStore().offset();
 400+ var divPopup = this._popup;
 401+ // get pointer to add ontop/onbottom class for it as well... IE6 support once again...
 402+ var divPointer = divPopup.children( '.' + this.POPUP_CLASS + '-pointer' )
 403+
 404+ // calc Y:
 405+ var posY = this._subject.offset().top - popupStoreOffset.top;
 406+ if( this._orientation.vertical === this.ORIENTATION.TOP ) { // get Y
 407+ // above subject
 408+ var yClassSuffix = '-ontop';
 409+ divPopup.addClass( this.POPUP_CLASS + '-ontop' )
 410+ divPointer.addClass( this.POPUP_CLASS + '-pointer-ontop' );
 411+ posY -= divPopup.outerHeight(); // height is different after classes are applied!
 412+ } else {
 413+ // underneath subject
 414+ var yClassSuffix = '-onbottom';
 415+ divPopup.addClass( this.POPUP_CLASS + '-onbottom' )
 416+ divPointer.addClass( this.POPUP_CLASS + '-pointer-onbottom' );
 417+ posY += this._subject.outerHeight();
 418+ }
 419+
 420+ // calc X:
 421+ var posX = -popupStoreOffset.left;
 422+ if( this._orientation.horizontal === this.ORIENTATION.LEFT ) {
 423+ // expand to left
 424+ divPopup.addClass( this.POPUP_CLASS + '-fromleft' );
 425+ posX += this._subject.offset().left + this._subject.outerWidth() - divPopup.outerWidth() // <<left
 426+ } else {
 427+ // expand to right
 428+ divPopup.addClass( this.POPUP_CLASS + '-fromright' );
 429+ posX += this._subject.offset().left; // right>>
 430+ }
 431+ // if popup would leave viewport (-10px tollerance), move it to the left until it fits...
 432+ var popupEndX = popupStoreOffset.left + posX + divPopup.outerWidth() + 10;
 433+ var viewPortEndeX = $( window ).scrollLeft() + $( window ).width();
 434+ var xOverflow = popupEndX - viewPortEndeX;
 435+ var origPosX = posX;
 436+ var xPointerMarging = 0;
 437+ if( xOverflow > 0 ) {
 438+ posX -= xOverflow;
 439+ xPointerMarging = xOverflow;
 440+ }
 441+ if( posX + popupStoreOffset.left <= 10 ) {
 442+ // ... except this would put the popup too far left
 443+ posX = -popupStoreOffset.left + 10; // 10px tollerance
 444+ xOverflow = origPosX - posX;
 445+ }
 446+
 447+ // apply calculated coordinates
 448+ divPopup.css( 'top', posY + 'px' );
 449+ divPopup.css( 'left', posX + 'px' );
 450+
 451+ // get popups pointer for adjustments
 452+ divPointer = divPopup.children( '.' + this.POPUP_CLASS + '-pointer' );
 453+
 454+ // if pointer goes over the right edge, move it to the edge and cut it nicely.
 455+ // this basically happens when popup is cut off on the right side by the viewport.
 456+ var margingSide = 'left';
 457+ var pointerEndX = xPointerMarging + divPointer.position().left + divPointer.width();
 458+ if( pointerEndX > divPopup.outerWidth() ) {
 459+ var divBox = divPopup.children( '.' + this.POPUP_CLASS + '-box' );
 460+ divPointer.css( 'border-right', divBox.css( 'border-right' ) );
 461+ divPointer.css( 'width', divPointer.width() / 2 );
 462+ if( this._orientation.horizontal == this.ORIENTATION.RIGHT ) {
 463+ xPointerMarging = divPopup.outerWidth() - ( divPointer.position().left + divPointer.outerWidth() );
 464+ xPointerMarging += 'px';
 465+ } else {
 466+ xPointerMarging = '-' + divPointer.css( 'right' );
 467+ margingSide = 'right';
 468+ }
 469+ }
 470+
 471+ divPointer.css( 'margin-' + margingSide, xPointerMarging );
 472+ },
 473+
 474+ /**
 475+ * Called by this.draw() when the popups html for the dom has to be built.
 476+ */
 477+ _draw_buildPopup: function() {
 478+ /*
 479+ * Inner div necessary because we need outer divs marging for the relative positioning.
 480+ * The inner divs marging is just good for some space between subject and box.
 481+ */
 482+ var divPopup; // outer div (for position marging/positioning)
 483+
 484+ if( this._popup === null ) {
 485+ divPopup = $( '<div/>' );
 486+
 487+ // if mouse can touch te popup:
 488+ if( this.isTouchable ) {
 489+ // when moving mouse from popup trigger element into popup, don't destroy popup!
 490+ var self = this;
 491+ divPopup.hover(
 492+ function() {self._hoverInFunc( self.PARTS.POPUP )},
 493+ function() {self._hoverOutFunc()}
 494+ );
 495+ }
 496+ }
 497+ else {
 498+ // just clean-up the existing popup for re-using it
 499+ divPopup = this._draw_existingPopupCleanup( this._popup );
 500+ }
 501+
 502+ divPopup
 503+ .addClass( this.POPUP_CLASS + ' ' + this.POPUP_ID )
 504+ .data( this.POPUP_CLASS, this ); // bind this object to element so child popups can get its parent
 505+
 506+ var divContent = $( '<div/>', { // inner div (for shadow and box shape + style marging)
 507+ 'class': this.POPUP_CLASS + '-box'
 508+ } );
 509+ var divPointer = $( '<div/>', { // div for arrow
 510+ 'class': this.POPUP_CLASS + '-pointer'
 511+ } );
 512+
 513+ divContent
 514+ .append( this._content ) // actual content
 515+ .appendTo( divPopup );
 516+
 517+ divPointer.appendTo( divPopup );
 518+
 519+ return divPopup;
 520+ },
 521+
 522+ /**
 523+ * Sub-Function of this._draw_buildPopup(), gets called when this.setContent() changes the content
 524+ * which leads to a re-draw. In that case we don't destroy the original popup but rather clean up
 525+ * what's necessary on the old one and re-use it.
 526+ * Basically this removes all children, css-styles and classes.
 527+ * @param divPopup jQuery the old popup
 528+ * @return jQuery the cleaned-up popup
 529+ */
 530+ _draw_existingPopupCleanup: function( divPopup ) {
 531+ divPopup.children().empty().remove();
 532+ return divPopup
 533+ .removeAttr( 'class' )
 534+ .removeAttr( 'style' );
 535+ },
 536+
 537+ /**
 538+ * Called whenever the popups content gets updated while the popup is still being displayed.
 539+ * In this case the popup size might change and perhaps it will be re-aligned which could
 540+ * lead to the mouse suddenly being outside of the popup. In this case some cleanup has to be
 541+ * done so the popup will fade out if the mouse doesn't re-enter soon.
 542+ *
 543+ * FIXME: IE 6+7 & Opera Bug: In case mouse is positioned within old popup content and after new
 544+ * content is applied the mouse doesn't move untill the fade timeout is out, the mosue
 545+ * event will not be triggered and therefore the popup will be closed.
 546+ * > This could be fixed with some permanent 'mousemove' event caching mouse position.
 547+ * > Might be worse performance but less complicated than current handling.
 548+ */
 549+ /*
 550+ _draw_contentUpdateCleanup: function( newPopup, newOrientation ) {
 551+ this._popup.unbind();
 552+ this._popup.empty().remove();
 553+
 554+ if( this._touchedPart != this.PARTS.SUBJECT ) {
 555+ if( newOrientation.vertical != this._orientation.vertical ) {
 556+ // popup now displayed on the other side, mouse must be outside now!
 557+ this._touchedPart = null;
 558+ this._setTimeTillFade( 1250 );
 559+ }
 560+ else {
 561+ // mouse could still be inside, no certainty!
 562+ var self = this;
 563+ var mouseMoveUnbind = function() {
 564+ self._subject.unbind( '.ContextPopupUpdateCleanup' );
 565+ newPopup.unbind( '.ContextPopupUpdateCleanup' );
 566+ };
 567+ var mouseMoveHandler = function( part ) {
 568+ return function() {
 569+ self._touchedPart = part;
 570+ self._clearTimeTillFade();
 571+ mouseMoveUnbind();
 572+ }
 573+ };
 574+ // destroy the popup in case the mouse is outside the popup now (due to positioning/size changes)...
 575+ this._setTimeTillFade( 1500, function() {
 576+ self._touchedPart = null;
 577+ mouseMoveUnbind();
 578+ } );
 579+
 580+ // ...unless we're still within popup-triggering territory (indicated by mouse-movement)
 581+ this._subject.bind( 'mousemove.ContextPopupUpdateCleanup', mouseMoveHandler( this.PARTS.SUBJECT ) );
 582+ newPopup.bind( 'mousemove.ContextPopupUpdateCleanup', mouseMoveHandler( this.PARTS.POPUP ) );
 583+ }
 584+ }
 585+ },
 586+ */
 587+
 588+ /**
 589+ * Calculates whether the information would best be displayed at top or bottom with left or
 590+ * right orientation relative to the element, considering the current viewport.
 591+ * @param popup jQuery dom element required for additional positioning calculation
 592+ * @return Object containing the properties 'horizontal' and 'vertical'
 593+ */
 594+ getIdealAlignment: function( popup ) {
 595+ var measurement = this.$package.InlineMeasurer.measure( this._subject );
 596+
 597+ // calculate viewport offset at top and bottom
 598+ var spaceT = this._subject.offset().top - $( window ).scrollTop();
 599+ var spaceB = $( window ).height() - spaceT - this._subject.outerHeight();
 600+
 601+ // calculate viewport offset left and right
 602+ var spaceL = this._subject.offset().left - $( window ).scrollLeft();
 603+ var spaceR = $( window ).width() - spaceL - this._subject.outerWidth();
 604+
 605+ var result = new Object();
 606+
 607+ result.vertical = ( // if enough space, always expand downwards
 608+ spaceT <= spaceB
 609+ || spaceB > ( popup.outerHeight() + 10 )
 610+ || this._subject.offset().top < ( popup.outerHeight() + 5 ) // never TOP if it would be cut off!
 611+ )
 612+ ? this.ORIENTATION.BOTTOM
 613+ : this.ORIENTATION.TOP;
 614+
 615+ result.horizontal = ( // if enough space, always expand to right if subject isn't a multi-line inline-element
 616+ !( !measurement.isOneLiner && result.vertical == this.ORIENTATION.TOP )
 617+ && (
 618+ spaceL <= spaceR
 619+ || ( spaceR + this._subject.outerWidth() ) > ( popup.outerWidth() + 10 )
 620+ || this._subject.offset().left < ( popup.outerWidth() + 5 ) // not LEFT if it would be cut off!
 621+ || ( !measurement.isOneLiner && result.vertical == this.ORIENTATION.BOTTOM )
 622+ )
 623+ )
 624+ ? this.ORIENTATION.RIGHT
 625+ : this.ORIENTATION.LEFT;
 626+
 627+ return result;
 628+ },
 629+
 630+ /**
 631+ * This will show the box if it is in a hidden state at the time.
 632+ * This will trigger the 'beforeShow' callback event.
 633+ * @return boolean whether visibility state has changed.
 634+ */
 635+ show: function() {
 636+ if( this._visible ) {
 637+ return false;
 638+ }
 639+ if( this.beforeShow != null && !this.beforeShow() ) { // callback
 640+ return false;
 641+ }
 642+ this._subject.addClass( this.POPUP_CLASS + '-subject-active' );
 643+ this._visible = true;
 644+ this.draw();
 645+
 646+ return true;
 647+ },
 648+
 649+ /**
 650+ * This will close the box if it is in an visible state at the moment.
 651+ * This will trigger the 'beforeClose' callback event.
 652+ * @return boolean whether visibility state has changed.
 653+ */
 654+ close: function() {
 655+ if( ! this._visible ) {
 656+ return false;
 657+ }
 658+ if( this.beforeClose != null && !this.beforeClose ) { // callback
 659+ return false;
 660+ }
 661+ // close child popups which might still be open for some reasons:
 662+ var openChild = this.getActiveChild();
 663+ if( openChild !== null ) {
 664+ openChild.close();
 665+ }
 666+ // effect for fade out but possibility to get a new popup at the same time alreaddy:
 667+ var popup = this._popup;
 668+ popup.unbind(); // unbind events so we can't get the popup back while its fading out
 669+ this._popup.fadeOut( this.TIME_TO_FADE_OUT, function() {
 670+ // Bug #101
 671+ popup.empty().remove();
 672+ } );
 673+ // remove popup from store:
 674+ this._popup = null;
 675+ this._visible = false;
 676+ this._orientation = null;
 677+ this._touchedPart = null;
 678+ this._subject.removeClass( this.POPUP_CLASS + '-subject-active' );
 679+ return true;
 680+ },
 681+
 682+ /**
 683+ * Whether the popup is visible at the moment
 684+ * @returns boolean
 685+ */
 686+ isVisible: function() {
 687+ return this._visible;
 688+ },
 689+
 690+ /**
 691+ * Returns the element which triggers the popup.
 692+ * @return jQuery
 693+ */
 694+ getSubject: function() {
 695+ return this._subject;
 696+ },
 697+
 698+ /**
 699+ * Returns the content which should be displayed within the popup container.
 700+ * @return jQuery
 701+ */
 702+ getContent: function() {
 703+ return this._content;
 704+ },
 705+
 706+ /**
 707+ * Allows to set the content of the box. The contents dimensions will define the boxes size
 708+ * in case the default css rules are not altered.
 709+ * @param content jQuery|String
 710+ */
 711+ setContent: function( content ) {
 712+ if( typeof content == 'undefined' ) {
 713+ content = '';
 714+ }
 715+ if( content instanceof String ) {
 716+ content = $( document.createTextNode( content ) );
 717+ }
 718+ this._content = content;
 719+ if( this._visible ) {
 720+ // refresh if content has changed
 721+ this.draw();
 722+ }
 723+ },
 724+
 725+ /**
 726+ * Returns the direct parent popup if any exists. If this is a top-level popup already, null will
 727+ * be returned. Consider that as long as the popup has its content hidden, there are no children
 728+ * because the parents subject would not be existant if hidden. Therefore the parent can only be
 729+ * returned as long as the parents content still exists within the DOM.
 730+ * @return ContextPopup|null
 731+ */
 732+ getParent: function() {
 733+ // check whether the subject has a popup container as one of its parents
 734+ var parent = this._subject.parents( '.' + this.POPUP_CLASS );
 735+ if( parent.length === 0 ) {
 736+ return null;
 737+ }
 738+ // the popup container should hold a data-'link' to its popup content instance
 739+ var parentObj = parent.eq(0).data( this.POPUP_CLASS );
 740+ if( typeof parentObj == 'undefined' ) {
 741+ return null;
 742+ }
 743+ return parentObj;
 744+ },
 745+
 746+ /**
 747+ * Returns all sub-popups within the popups content.
 748+ * @return Array contains the ContextPopup child instances
 749+ */
 750+ getChildren: function() {
 751+ var ChildPopups = new Array();
 752+ if( !( this._content instanceof jQuery ) ) {
 753+ return ChildPopups;
 754+ }
 755+ var childSubjects = this._content.find( '.' + this.POPUP_CLASS + '-subject' );
 756+ var i = 0;
 757+ var self = this;
 758+ childSubjects.each( function() {
 759+ // check for potential subjects data which should be a ContextPopup instance
 760+ childObj = $( this ).data( self.POPUP_CLASS );
 761+ if( typeof childObj != 'undefined' ) {
 762+ ChildPopups[i++] = childObj;
 763+ }
 764+ } );
 765+ return ChildPopups;
 766+ },
 767+
 768+ /**
 769+ * Returns the direct active sub-popup. There can only be one direct active sub-popup
 770+ * at a time. In case no sub-popup exists or none is active, null will be returned.
 771+ * @return ContextPopup|null
 772+ */
 773+ getActiveChild: function() {
 774+ var childPopups = this.getChildren();
 775+ for( var i = 0; i < childPopups.length; i++ ) {
 776+ var child = childPopups[i];
 777+ if( child.isVisible() ) {
 778+ // mouse entered sub-popup, don't make this (parent) popup disappear!
 779+ return child;
 780+ }
 781+ }
 782+ return null;
 783+ },
 784+
 785+ ///////////
 786+ // EVENTS:
 787+ ///////////
 788+
 789+ /**
 790+ * Callback which is being called before the popup is changing its state from closed to displayed.
 791+ * If this returns false, showing the popup will be prevented.
 792+ */
 793+ beforeShow: null,
 794+
 795+ /**
 796+ * Callback which is being called before the popup is changing its state from displayed to closed.
 797+ * If this returns false, closing the popup will be prevented.
 798+ */
 799+ beforeClose: null,
 800+
 801+ /////////////////
 802+ // CONFIGURABLE:
 803+ /////////////////
 804+
 805+ /**
 806+ * Allows to configurate whether or not the popup will still stay when the mouse moves
 807+ * from subject object into the popup.
 808+ * @var boolean
 809+ */
 810+ isTouchable: true
 811+};
Property changes on: trunk/extensions/SemanticExpressiveness/resources/ext.semex.ui.ContextPopup.js
___________________________________________________________________
Added: svn:eol-style
1812 + native
Index: trunk/extensions/SemanticExpressiveness/README
@@ -0,0 +1,46 @@
 2+== About ==
 3+
 4+~~ THIS IS NOT A FINAL RELEASE YET, ITS CONSIDERED AN ALPHA VERSION BY NOW ~~
 5+
 6+The 'Semantic Expressiveness' extension is an enhancement for 'Semantic MediaWiki'.
 7+Its main feature is to introduce a new syntax for inline short queries. The purpose
 8+of this simplest form of inline query is to fight redundancies within the wiki.
 9+Without 'Semantic Expressivenss' it is customary to declare properties in one place
 10+but using the same information again all over the same article or on other pages.
 11+With 'Semantic Expressiveness' it is possible to use simple references in form of a
 12+new syntax to place the same information in various places without writing redundant
 13+information. This way if the property changes, the information will update itself
 14+all over the wiki wherever the new syntax is in place.
 15+There are also further features like parser functions for template developers and a
 16+JavaScript context popup using AJAX to display further information on cross-article
 17+inline queries.
 18+
 19+* Website: https://www.mediawiki.org/wiki/Extension:Semantic_Expressiveness
 20+* License: GPL v3
 21+* Author: Daniel Werner < danweetz@web.de >
 22+
 23+
 24+== Installation ==
 25+
 26+Once you have downloaded the code, place the 'SemanticExpressiveness' directory within
 27+your MediaWiki 'extensions' directory. Then add the following code to your
 28+[[Manual:LocalSettings.php|LocalSettings.php]] file:
 29+
 30+ # Semantic Expressiveness
 31+ require_once( "$IP/extensions/SemanticExpressiveness/SemanticExpressiveness.php" );
 32+
 33+This extension requires Jeroen De Dauws 'Validator' extension (version 0.4.14 or
 34+above). It must be included before the 'Semantic Expressiveness' extension.
 35+You can get it at: http://www.mediawiki.org/wiki/Extension:Validator
 36+
 37+Furthermore, PHP 5.3+ is required and currently it is necessary to apply a patch for
 38+MediaWiki bug #34678 manually:
 39+https://bugzilla.wikimedia.org/attachment.cgi?id=10095&action=diff
 40+
 41+
 42+== Contributing ==
 43+
 44+If you have bug reports or feature requests, please add them to the 'Semantic Expressiveness'
 45+Talk page [0]. You can also send them to Daniel Werner < danweetz@web.de >
 46+
 47+[0] https://www.mediawiki.org/w/index.php?title=Extension_talk:Semantic_Expressiveness
Index: trunk/extensions/SemanticExpressiveness/SemanticExpressiveness.i18n.magic.php
@@ -0,0 +1,15 @@
 2+<?php
 3+/**
 4+ * Internationalisation file for 'SemanticExpressiveness' extension.
 5+ *
 6+ * @ingroup SemanticExpressiveness
 7+ * @author Daniel Werner < danweetz@web.de >
 8+ */
 9+
 10+$magicWords = array();
 11+
 12+$magicWords['en'] = array(
 13+ '?' => array( 0, '?' ),
 14+ '?!' => array( 0, '?!' ),
 15+ '?to?!' => array( 0, '?to?!' ),
 16+);
Property changes on: trunk/extensions/SemanticExpressiveness/SemanticExpressiveness.i18n.magic.php
___________________________________________________________________
Added: svn:eol-style
117 + native
Index: trunk/extensions/SemanticExpressiveness/SemanticExpressiveness.i18n.php
@@ -0,0 +1,43 @@
 2+<?php
 3+/**
 4+ * Internationalisation file for 'SemanticExpressiveness' extension.
 5+ *
 6+ * @ingroup SemanticExpressiveness
 7+ * @author Daniel Werner < danweetz@web.de >
 8+ */
 9+
 10+$messages = array();
 11+
 12+/** English
 13+ * @author Daniel Werner
 14+ */
 15+$messages['en'] = array(
 16+ 'semex-desc' => 'Adds a syntax for more expressive short queries.',
 17+ 'semex-shortquery-title' => '$1 from $2',
 18+ 'semex-shortquery-title-from-ref' => '$1 from ref $2',
 19+ 'semex-shortquery-hover-loading' => 'Loading',
 20+ 'semex-shortquery-hover-loading-failed' => 'Loading the short queries target pages content failed.',
 21+ 'semex-shortquery-error-missing-property' => 'No value defined for the queried property.',
 22+ 'semex-shortquery-error-byref-has-many-values' => 'The given reference property has more than one value, only the first one was taken as the queries target.',
 23+ 'semex-shortquery-error-byref-has-wrong-type' => 'The given reference property should be one of type "Page".',
 24+ 'semex-shortquery-error-failed-nested-queries' => 'Short query can not be executed because nested short query failed.',
 25+ 'semex-expressivestring-unresolvable' => 'Unresolvable markup',
 26+);
 27+
 28+/** Message documentation (Message documentation)
 29+ * @author Daniel Werner
 30+ */
 31+$messages['qqq'] = array(
 32+ 'semex-shortquery-title' => '<$1: semantic property name> from <$2: page the query got the property value from>',
 33+ 'semex-shortquery-title-from-ref' => '<$1: semantic property name> from reference <$2: another semantic property name of the same page>',
 34+);
 35+
 36+/** German (Deutsch)
 37+ * @author Daniel Werner
 38+ */
 39+$messages['de'] = array(
 40+ 'semex-shortquery-title' => '$1 von $2',
 41+ 'semex-shortquery-title-from-ref' => '$1 von Ref $2',
 42+ 'semex-shortquery-hover-loading' => 'Läd<i>t</i>',
 43+ 'semex-shortquery-hover-loading-failed' => 'Laden des Inhalts der Quell-Seite der Kurz-Abfrage schlug fehl.',
 44+);
Property changes on: trunk/extensions/SemanticExpressiveness/SemanticExpressiveness.i18n.php
___________________________________________________________________
Added: svn:eol-style
145 + native

Status & tagging log