http://www.mediawiki.org/wiki/Special:Code/MediaWiki/89140

Revision: 89140
Author:   foxtrott
Date:     2011-05-29 23:03:25 +0000 (Sun, 29 May 2011)
Log Message:
-----------
Improved markup algorithm (handles special chars and spaces, optimized)

Modified Paths:
--------------
    trunk/extensions/SemanticGlossary/SemanticGlossary.php
    trunk/extensions/SemanticGlossary/SemanticGlossaryElement.php
    trunk/extensions/SemanticGlossary/SemanticGlossaryParser.php

Added Paths:
-----------
    trunk/extensions/SemanticGlossary/SemanticGlossaryTree.php

Modified: trunk/extensions/SemanticGlossary/SemanticGlossary.php
===================================================================
--- trunk/extensions/SemanticGlossary/SemanticGlossary.php      2011-05-29 
22:49:54 UTC (rev 89139)
+++ trunk/extensions/SemanticGlossary/SemanticGlossary.php      2011-05-29 
23:03:25 UTC (rev 89140)
@@ -53,6 +53,7 @@
 // register class files with the Autoloader
 $wgAutoloadClasses[ 'SemanticGlossarySettings' ] = $dir . 
'/SemanticGlossarySettings.php';
 $wgAutoloadClasses[ 'SemanticGlossaryParser' ] = $dir . 
'/SemanticGlossaryParser.php';
+$wgAutoloadClasses[ 'SemanticGlossaryTree' ] = $dir . 
'/SemanticGlossaryTree.php';
 $wgAutoloadClasses[ 'SemanticGlossaryElement' ] = $dir . 
'/SemanticGlossaryElement.php';
 $wgAutoloadClasses[ 'SemanticGlossaryMessageLog' ] = $dir . 
'/SemanticGlossaryMessageLog.php';
 $wgAutoloadClasses[ 'SpecialSemanticGlossaryBrowser' ] = $dir . 
'/SpecialSemanticGlossaryBrowser.php';

Modified: trunk/extensions/SemanticGlossary/SemanticGlossaryElement.php
===================================================================
--- trunk/extensions/SemanticGlossary/SemanticGlossaryElement.php       
2011-05-29 22:49:54 UTC (rev 89139)
+++ trunk/extensions/SemanticGlossary/SemanticGlossaryElement.php       
2011-05-29 23:03:25 UTC (rev 89140)
@@ -19,38 +19,35 @@
  * @ingroup SemanticGlossary
  */
 class SemanticGlossaryElement {
+       const SG_TERM = 0;
        const SG_DEFINITION = 1;
        const SG_SOURCE = 2;
        const SG_LINK = 3;
 
-       private $mTerm;
        private $mFullDefinition = null;
        private $mDefinitions = array( );
        static private $mLinkTemplate = null;
 
-       public function __construct ( $term=null, $definition=null, $link=null, 
$source=null ) {
-               $this -> mTerm = $term;
-               $this -> addDefinition( $definition, $link, $source );
+       public function __construct ( &$definition=null ) {
+               if ( $definition ) {
+                       $this -> addDefinition( $definition );
+               }
        }
 
-       public function addDefinition ( $definition=null, $link=null, 
$source=null ) {
+       public function addDefinition ( &$definition ) {
 
-               $this -> mDefinitions[ ] = array(
-                       self::SG_DEFINITION => $definition,
-                       self::SG_SOURCE => $source,
-                       self::SG_LINK => $link,
-               );
+                       $this ->mDefinitions[] = $definition;
        }
 
        public function getFullDefinition ( DOMDocument &$doc ) {
 
                // only create if not yet created
-               if ( $this -> mFullDefinition == null ) {
+               if ( $this -> mFullDefinition == null || $this -> 
mFullDefinition -> ownerDocument !== $doc ) {
 
                        $this -> mFullDefinition = $doc -> createElement( 
'span' );
 
                        foreach ( $this -> mDefinitions as $definition ) {
-                               $element = $doc -> createElement( 'span', 
html_entity_decode( $definition[ self::SG_DEFINITION ], ENT_COMPAT, 'UTF-8' ) . 
' ' );
+                               $element = $doc -> createElement( 'span', 
htmlentities( $definition[ self::SG_DEFINITION ], ENT_COMPAT, 'UTF-8' ) . ' ' );
                                if ( $definition[ self::SG_LINK ] ) {
                                        $linkedTitle = Title::newFromText( 
$definition[ self::SG_LINK ] );
                                        if ( $linkedTitle ) {
@@ -70,15 +67,19 @@
                return key( $this -> mDefinitions );
        }
 
-       public function getSource ( $key ) {
+//     public function getTerm ( $key ) {
+//             return $this -> mDefinitions[ $key ][ self::SG_TERM ];
+//     }
+//
+       public function getSource ( &$key ) {
                return $this -> mDefinitions[ $key ][ self::SG_SOURCE ];
        }
 
-       public function getDefinition ( $key ) {
+       public function getDefinition ( &$key ) {
                return $this -> mDefinitions[ $key ][ self::SG_DEFINITION ];
        }
 
-       public function getLink ( $key ) {
+       public function getLink ( &$key ) {
                return $this -> mDefinitions[ $key ][ self::SG_LINK ];
        }
 
@@ -87,7 +88,7 @@
        }
 
        private function getLinkTemplate ( DOMDocument &$doc ) {
-               
+
                // create template if it does not yet exist
                if ( !self::$mLinkTemplate || ( self::$mLinkTemplate -> 
ownerDocument !== $doc ) ) {
 

Modified: trunk/extensions/SemanticGlossary/SemanticGlossaryParser.php
===================================================================
--- trunk/extensions/SemanticGlossary/SemanticGlossaryParser.php        
2011-05-29 22:49:54 UTC (rev 89139)
+++ trunk/extensions/SemanticGlossary/SemanticGlossaryParser.php        
2011-05-29 23:03:25 UTC (rev 89140)
@@ -22,6 +22,10 @@
  */
 class SemanticGlossaryParser {
 
+       private $mGlossaryArray = null;
+       private $mGlossaryTree = null;
+       private static $parserSingleton = null;
+
        /**
         *
         * @param $parser
@@ -31,10 +35,14 @@
        static function parse ( &$parser, &$text ) {
 
                wfProfileIn( __METHOD__ );
+//             echo( __METHOD__ );
 
-               $sl = new SemanticGlossaryParser();
-               $sl -> realParse( $parser, $text );
+               if ( !self::$parserSingleton ) {
+                       self::$parserSingleton = new SemanticGlossaryParser();
+               }
 
+               self::$parserSingleton -> realParse( $parser, $text );
+
                wfProfileOut( __METHOD__ );
 
                return true;
@@ -42,15 +50,48 @@
 
        /**
         * Returns the list of terms applicable in the current context
-        * 
+        *
         * @return Array an array mapping terms (keys) to descriptions (values)
         */
        function getGlossaryArray ( SemanticGlossaryMessageLog &$messages = 
null ) {
 
-               global $smwgQDefaultNamespaces;
+               wfProfileIn( __METHOD__ );
 
+               // build glossary array only once per request
+               if ( !$this -> mGlossaryArray ) {
+                       $this -> buildGlossary( $messages );
+               }
+
+               wfProfileOut( __METHOD__ );
+
+               return $this -> mGlossaryArray;
+       }
+
+       /**
+        * Returns the list of terms applicable in the current context
+        *
+        * @return Array an array mapping terms (keys) to descriptions (values)
+        */
+       function getGlossaryTree ( SemanticGlossaryMessageLog &$messages = null 
) {
+
                wfProfileIn( __METHOD__ );
 
+               // build glossary array only once per request
+               if ( !$this -> mGlossaryTree ) {
+                       $this -> buildGlossary( $messages );
+               }
+
+               wfProfileOut( __METHOD__ );
+
+               return $this -> mGlossaryTree;
+       }
+
+       protected function buildGlossary ( SemanticGlossaryMessageLog 
&$messages = null ) {
+
+               wfProfileIn( __METHOD__ );
+
+               $this -> mGlossaryTree = new SemanticGlossaryTree();
+
                $store = smwfGetStore(); // default store
                // Create query
                $desc = new SMWSomeProperty( new SMWDIProperty( '___glt' ), new 
SMWThingDescription() );
@@ -69,7 +110,7 @@
                $queryresult = $store -> getQueryResult( $query );
 
                // assemble the result array
-               $result = array( );
+               $this -> mGlossaryArray = array( );
                while ( ( $resultline = $queryresult -> getNext() ) ) {
 
                        $term = $resultline[ 0 ] -> getNextText( 
SMW_OUTPUT_HTML );
@@ -98,18 +139,25 @@
                                continue;
                        }
 
-                       $source = array( $subject -> getDBkey(), $subject -> 
getNamespace(), $subject -> getInterwiki(), $subject -> getDBkey() );
+                       $source = array( $subject -> getDBkey(), $subject -> 
getNamespace(), $subject -> getInterwiki() );
 
-                       if ( array_key_exists( $term, $result ) ) {
-                               $result[ $term ] -> addDefinition( $definition, 
$link, $source );
+                       $elementData = array(
+                               SemanticGlossaryElement::SG_TERM => $term,
+                               SemanticGlossaryElement::SG_DEFINITION => 
$definition,
+                               SemanticGlossaryElement::SG_LINK => $link,
+                               SemanticGlossaryElement::SG_SOURCE => $source
+                       );
+
+                       if ( array_key_exists( $term, $this -> mGlossaryArray ) 
) {
+                               $this -> mGlossaryArray[ $term ] -> 
addDefinition( $elementData );
                        } else {
-                               $result[ $term ] = new SemanticGlossaryElement( 
$term, $definition, $link, $source );
+                               $this -> mGlossaryArray[ $term ] = new 
SemanticGlossaryElement( $elementData );
                        }
+
+                       $this -> mGlossaryTree -> addTerm( $term, $elementData 
);
                }
 
                wfProfileOut( __METHOD__ );
-
-               return $result;
        }
 
        /**
@@ -126,83 +174,220 @@
                global $wgRequest, $sggSettings;
 
                wfProfileIn( __METHOD__ );
+//             echo( __METHOD__ );
 
                $action = $wgRequest -> getVal( 'action', 'view' );
-               if ( $text == null || $text == '' || $action == "edit" || 
$action == "ajax" || isset( $_POST[ 'wpPreview' ] ) )
+
+               if ( $text == null ||
+                       $text == '' ||
+                       $action == "edit" ||
+                       $action == "ajax" ||
+                       isset( $_POST[ 'wpPreview' ] )
+               ) {
+
+                       wfProfileOut( __METHOD__ );
                        return true;
+               }
+
                // Get array of terms
-               $terms = $this -> getGlossaryArray();
+               $glossary = $this -> getGlossaryTree();
+//
+//             if ( empty( $terms ) ) {
+               if ( $glossary == null ) {
 
-               if ( empty( $terms ) )
+                       wfProfileOut( __METHOD__ );
                        return true;
+               }
 
                //Get the minimum length abbreviation so we don't bother 
checking against words shorter than that
-               $min = min( array_map( 'strlen', array_keys( $terms ) ) );
-
+//             $min = min( array_map( 'strlen', array_keys( $terms ) ) );
                //Parse HTML from page
                // FIXME: this works in PHP 5.3.3. What about 5.1?
+               wfProfileIn( __METHOD__ . " 1 loadHTML" );
                wfSuppressWarnings();
-               $doc = DOMDocument::loadHTML( '<html><meta 
http-equiv="content-type" content="charset=utf-8"/>' . $text . '</html>' );
+
+               $doc = DOMDocument::loadHTML(
+                               '<html><meta http-equiv="content-type" 
content="charset=utf-8"/>' . $text . '</html>'
+               );
+
                wfRestoreWarnings();
+               wfProfileOut( __METHOD__ . " 1 loadHTML" );
 
+               wfProfileIn( __METHOD__ . " 2 xpath" );
                //Find all text in HTML.
                $xpath = new DOMXpath( $doc );
-               $elements = $xpath -> query( 
"//*[not(ancestor-or-self::*[@class='noglossary'] or 
ancestor-or-self::a)][text()!=' ']/text()" );
+               $elements = $xpath -> query(
+                               
"//*[not(ancestor-or-self::*[@class='noglossary'] or 
ancestor-or-self::a)][text()!=' ']/text()"
+               );
+               wfProfileOut( __METHOD__ . " 2 xpath" );
 
                //Iterate all HTML text matches
                $nb = $elements -> length;
-               $changed = false;
+               $changedDoc = false;
 
                for ( $pos = 0; $pos < $nb; $pos++ ) {
 
                        $el = $elements -> item( $pos );
 
-                       if ( strlen( $el -> nodeValue ) < $min )
+                       if ( strlen( $el -> nodeValue ) < $glossary -> 
getMinTermLength() ) {
                                continue;
+                       }
 
-                       //Split node text into words, putting offset and text 
into $offsets[0] array
-//                     preg_match_all( "/\b[^\b\s\.,;:]+/", $el -> nodeValue, 
$offsets, PREG_OFFSET_CAPTURE );
-                       preg_match_all( "/[^\s{$sggSettings -> 
punctuationCharacters}]+/", $el -> nodeValue, $offsets, PREG_OFFSET_CAPTURE );
+                       wfProfileIn( __METHOD__ . " 3 lexer" );
+                       $matches = array( );
+                       preg_match_all( '/[[:alpha:]]+|[^[:alpha:]]/', $el -> 
nodeValue, $matches, PREG_OFFSET_CAPTURE | PREG_PATTERN_ORDER );
+                       wfProfileOut( __METHOD__ . " 3 lexer" );
 
-                       //Search and replace words in reverse order (from end 
of string backwards),
-                       //This way we don't mess up the offsets of the words as 
we iterate
-                       $len = count( $offsets[ 0 ] );
+                       if ( count( $matches ) == 0 || count( $matches[ 0 ] ) 
== 0 ) {
+                               continue;
+                       }
 
-                       for ( $i = $len - 1; $i >= 0; $i-- ) {
+                       $lexemes = &$matches[ 0 ];
+                       $countLexemes = count( $lexemes );
+                       $parent = &$el -> parentNode;
+                       $index = 0;
+                       $changedElem = false;
 
-                               $offset = $offsets[ 0 ][ $i ];
+//                     echo("\nrealParse: nodeValue: {$el->nodeValue}\n");
+                       while ( $index < $countLexemes ) {
 
-                               //Check if word is an abbreviation from the 
terminologies
-                               if ( !is_numeric( $offset[ 0 ] ) && isset( 
$terms[ $offset[ 0 ] ] ) ) { //Word matches, replace with appropriate span tag
-                                       $changed = true;
+                               wfProfileIn( __METHOD__ . " 4 findNextTerm" );
+                               list( $skipped, $used, $definition ) = 
$glossary -> findNextTerm( $lexemes, $index, $countLexemes );
+                               wfProfileOut( __METHOD__ . " 4 findNextTerm" );
 
-                                       $beforeMatchNode = $doc -> 
createTextNode( substr( $el -> nodeValue, 0, $offset[ 1 ] ) );
-                                       $afterMatchNode = $doc -> 
createTextNode( substr( $el -> nodeValue, $offset[ 1 ] + strlen( $offset[ 0 ] 
), strlen( $el -> nodeValue ) - 1 ) );
+//                             echo("realParse: skipped: $skipped  used: 
$used\n");
+//                             var_export($definition);
 
+                               wfProfileIn( __METHOD__ . " 5 insert" );
+                               if ( $used > 0 ) { // found a term
+                                       if ( $skipped > 0 ) { // skipped some 
text, insert it as is
+
+                                               $parent -> insertBefore(
+                                                       $doc -> createTextNode(
+                                                               substr( $el -> 
nodeValue,
+                                                                       
$currLexIndex = $lexemes[ $index ][ 1 ],
+                                                                       
$lexemes[ $index + $skipped ][ 1 ] - $currLexIndex )
+                                                       ),
+                                                       $el
+                                               );
+                                       }
+
+                                       $index += $skipped;
+
                                        //Wrap abbreviation in <span> tags
                                        $span = $doc -> createElement( 'span' );
                                        $span -> setAttribute( 'class', 
"tooltip" );
 
                                        //Wrap abbreviation in <span> tags, 
hidden
-                                       $spanAbr = $doc -> createElement( 
'span', $offset[ 0 ] );
-                                       $spanAbr -> setAttribute( 'class', 
"tooltip_abbr" );
+                                       $lastLex = $lexemes[ $index + $used - 1 
];
+                                       $spanTerm = $doc -> createElement( 
'span',
+                                                       substr( $el -> 
nodeValue,
+                                                               $currLexIndex = 
$lexemes[ $index ][ 1 ],
+                                                               $lastLex[ 1 ] - 
$currLexIndex + strlen( $lastLex[ 0 ] ) )
+                                       );
+                                       $spanTerm -> setAttribute( 'class', 
"tooltip_abbr" );
 
                                        //Wrap definition in <span> tags, hidden
-                                       $spanTip = $terms[ $offset[ 0 ] ] -> 
getFullDefinition( $doc );
-                                       $spanTip -> setAttribute( 'class', 
"tooltip_tip" );
+                                       $spanDefinition = $definition -> 
getFullDefinition( $doc );
+                                       $spanDefinition -> setAttribute( 
'class', "tooltip_tip" );
 
-                                       $el -> parentNode -> insertBefore( 
$beforeMatchNode, $el );
-                                       $el -> parentNode -> insertBefore( 
$span, $el );
-                                       $span -> appendChild( $spanAbr );
-                                       $span -> appendChild( $spanTip );
-                                       $el -> parentNode -> insertBefore( 
$afterMatchNode, $el );
-                                       $el -> parentNode -> removeChild( $el );
-                                       $el = $beforeMatchNode; //Set new 
element to the text before the match for next iteration
+                                       // insert term and definition
+                                       $span -> appendChild( $spanTerm );
+                                       $span -> appendChild( $spanDefinition );
+                                       $parent -> insertBefore( $span, $el );
+
+                                       $changedElem = true;
+                               } else { // did not find term, just use the 
rest of the text
+                                       // If we found no term now and no term 
before, there was no
+                                       // term in the whole element. Might as 
well not change the
+                                       // element at all.
+                                       // Only change element if found term 
before
+                                       if ( $changedElem ) {
+                                               $parent -> insertBefore(
+                                                       $doc -> createTextNode(
+                                                               substr( $el -> 
nodeValue, $lexemes[ $index ][ 1 ] )
+                                                       ),
+                                                       $el
+                                               );
+                                       } else {
+
+                                               wfProfileOut( __METHOD__ . " 5 
insert" );
+                                               // In principle superfluous, 
the loop would run out
+                                               // anyway. Might save a bit of 
time.
+                                               break;
+                                       }
+
+                                       $index += $skipped;
                                }
+                               wfProfileOut( __METHOD__ . " 5 insert" );
+
+
+                               $index += $used;
                        }
+
+                       if ( $changedElem ) {
+                               $parent -> removeChild( $el );
+                               $changedDoc = true;
+                       }
+
+                       //Split node text into words, putting offset and text 
into $offsets[0] array
+//                     preg_match_all(
+//                             "/[^\s{$sggSettings -> 
punctuationCharacters}]+/",
+//                             $el -> nodeValue,
+//                             $offsets,
+//                             PREG_OFFSET_CAPTURE
+//                     );
+//
+//                     var_export($offsets);
+//
+//                     //Search and replace words in reverse order (from end 
of string backwards),
+//                     //This way we don't mess up the offsets of the words as 
we iterate
+//                     $len = count( $offsets[ 0 ] );
+//
+//                     for ( $i = $len - 1; $i >= 0; $i-- ) {
+//
+//                             $offset = $offsets[ 0 ][ $i ];
+//
+//                             //Check if word is an abbreviation from the 
terminologies
+//                             if ( !is_numeric( $offset[ 0 ] ) && isset( 
$terms[ $offset[ 0 ] ] ) ) {
+//                                     //Word matches, replace with 
appropriate span tag
+//
+//                                     $changed = true;
+//
+//                                     $beforeMatchNode = $doc -> 
createTextNode(
+//                                                     substr( $el -> 
nodeValue, 0, $offset[ 1 ] )
+//                                     );
+//
+//                                     $afterMatchNode = $doc -> 
createTextNode(
+//                                                     substr( $el -> 
nodeValue,
+//                                                             $offset[ 1 ] + 
strlen( $offset[ 0 ] ),
+//                                                             strlen( $el -> 
nodeValue ) - 1 )
+//                                     );
+//
+//                                     //Wrap abbreviation in <span> tags
+//                                     $span = $doc -> createElement( 'span' );
+//                                     $span -> setAttribute( 'class', 
"tooltip" );
+//
+//                                     //Wrap abbreviation in <span> tags, 
hidden
+//                                     $spanAbr = $doc -> createElement( 
'span', $offset[ 0 ] );
+//                                     $spanAbr -> setAttribute( 'class', 
"tooltip_abbr" );
+//
+//                                     //Wrap definition in <span> tags, hidden
+//                                     $spanTip = $terms[ $offset[ 0 ] ] -> 
getFullDefinition( $doc );
+//                                     $spanTip -> setAttribute( 'class', 
"tooltip_tip" );
+//
+//                                     $el -> parentNode -> insertBefore( 
$beforeMatchNode, $el );
+//                                     $el -> parentNode -> insertBefore( 
$span, $el );
+//                                     $span -> appendChild( $spanAbr );
+//                                     $span -> appendChild( $spanTip );
+//                                     $el -> parentNode -> insertBefore( 
$afterMatchNode, $el );
+//                                     $el -> parentNode -> removeChild( $el );
+//                                     $el = $beforeMatchNode; //Set new 
element to the text before the match for next iteration
+//                             }
+//                     }
                }
 
-               if ( $changed ) {
+               if ( $changedDoc ) {
                        $body = $xpath -> query( '/html/body' );
 //                     $text = $doc -> saveXML( $body -> item( 0 ) );
 
@@ -219,8 +404,10 @@
                return true;
        }
 
-       protected function loadModules ( &$parser ) {
+       protected
 
+       function loadModules ( &$parser ) {
+
                global $wgOut, $wgScriptPath;
 
                if ( defined( 'MW_SUPPORTS_RESOURCE_MODULES' ) ) {
@@ -240,3 +427,4 @@
        }
 
 }
+

Added: trunk/extensions/SemanticGlossary/SemanticGlossaryTree.php
===================================================================
--- trunk/extensions/SemanticGlossary/SemanticGlossaryTree.php                  
        (rev 0)
+++ trunk/extensions/SemanticGlossary/SemanticGlossaryTree.php  2011-05-29 
23:03:25 UTC (rev 89140)
@@ -0,0 +1,140 @@
+<?php
+
+/**
+ * File holding the SemanticGlossaryTree class
+ * 
+ * @author Stephan Gambke
+ * @file
+ * @ingroup SemanticGlossary
+ */
+if ( !defined( 'SG_VERSION' ) ) {
+       die( 'This file is part of the SemanticGlossary extension, it is not a 
valid entry point.' );
+}
+
+/**
+ * The SemanticGlossaryTree class.
+ *
+ * Vocabulary:
+ * Term - The term as a normal string
+ * Definition - Its definition object
+ * Element - An element (leaf) in the glossary tree
+ * Path - The path in the tree to the leaf representing a term
+ *
+ * @ingroup SemanticGlossary
+ */
+class SemanticGlossaryTree {
+
+       private $mTree = array( );
+       private $mDefinition = null;
+       private $mMinLength = -1;
+
+       /**
+        * Adds a string to the Glossary Tree
+        * @param String $term
+        */
+       function addTerm ( &$term, $definition ) {
+
+               if ( !$term ) {
+                       return;
+               }
+
+               $matches;
+               preg_match_all( '/[[:alpha:]]+|[^[:alpha:]]/', $term, $matches 
);
+
+               $this -> addElement( $matches[ 0 ], $definition );
+
+               if ( $this -> mMinLength > -1 ) {
+                       $this -> mMinLength = min( array( $this -> mMinLength, 
strlen( $term ) ) );
+               } else {
+                       $this -> mMinLength = strlen( $term );
+               }
+       }
+
+       /**
+        *      Recursively adds an element to the Glossary Tree
+        *
+        * @param array $path
+        * @param <type> $index
+        */
+       protected function addElement ( Array &$path, &$definition ) {
+
+               // end of path, store description; end of recursion
+               if ( $path == null ) {
+
+                       $this -> addDefinition( $definition );
+               } else {
+
+                       $step = array_shift( $path );
+
+                       if ( !array_key_exists( $step, $this -> mTree ) ) {
+
+                               $this -> mTree[ $step ] = new 
SemanticGlossaryTree();
+                       }
+
+                       $this -> mTree[ $step ] -> addElement( $path, 
$definition );
+               }
+       }
+
+       /**
+        * Adds a defintion to the treenodes list of definitions
+        * @param <type> $definition
+        */
+       protected function addDefinition ( &$definition ) {
+
+               if ( $this -> mDefinition ) {
+                       $this -> mDefinition -> addDefinition( $definition );
+               } else {
+                       $this -> mDefinition = new SemanticGlossaryElement( 
$definition );
+               }
+       }
+
+       function getMinTermLength () {
+               return $this -> mMinLength;
+       }
+
+       function findNextTerm ( &$lexemes, $index, $countLexemes ) {
+
+               wfProfileIn( __METHOD__ );
+
+               $start = $lastindex = $index;
+               $definition = null;
+
+               // skip until ther start of a term is found
+               while ( $index < $countLexemes && !$definition ) {
+
+                       $currLex = &$lexemes[ $index ][ 0 ];
+                       
+                       // Did we find the start of a term?
+                       if ( array_key_exists( $currLex, $this -> mTree ) ) {
+
+                               list( $lastindex, $definition) = $this -> 
mTree[ $currLex ] -> findNextTermNoSkip( $lexemes, $index, $countLexemes );
+                       }
+
+                       // this will increase the index even if we found 
something;
+                       // will be corrected after the loop
+                       $index++;
+               }
+
+               wfProfileOut( __METHOD__ );
+               if ( $definition ) {
+                       return array( $index - $start - 1, $lastindex - $index 
+ 2, $definition );
+               } else {
+                       return array( $index - $start, 0, null );
+               }
+       }
+
+       function findNextTermNoSkip ( &$lexemes, $index, $countLexemes ) {
+               wfProfileIn( __METHOD__ );
+
+               if ( $index + 1 < $countLexemes && array_key_exists( $currLex = 
$lexemes[ $index + 1 ][ 0 ], $this -> mTree ) ) {
+
+                       $ret = $this -> mTree[ $currLex ] -> 
findNextTermNoSkip( $lexemes, $index + 1, $countLexemes );
+               } else {
+
+                       $ret = array( $index, &$this -> mDefinition );
+               }
+               wfProfileOut( __METHOD__ );
+               return $ret;
+       }
+
+}


Property changes on: trunk/extensions/SemanticGlossary/SemanticGlossaryTree.php
___________________________________________________________________
Added: svn:eol-style
   + native


_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to