Index: trunk/extensions/Lingo/Lingo.php |
— | — | @@ -1,140 +1,158 @@ |
2 | 2 | <?php |
3 | | - |
4 | 3 | /** |
5 | | - * Provides hover-over tool tips on articles from words defined on the Terminology page. |
6 | | - * For more info see http://mediawiki.org/wiki/Extension:Lingo |
| 4 | + * Provides hover-over tool tips on articles from words defined on the |
| 5 | + * Terminology page. |
7 | 6 | * |
| 7 | + * @file |
8 | 8 | * @defgroup Lingo |
9 | 9 | * @author Barry Coughlan |
10 | 10 | * @copyright 2010 Barry Coughlan |
11 | 11 | * @version 0.1 |
12 | 12 | * @licence GNU General Public Licence 2.0 or later |
| 13 | + * @see http://www.mediawiki.org/wiki/Extension:Lingo Documentation |
13 | 14 | */ |
14 | 15 | if ( !defined( 'MEDIAWIKI' ) ) { |
15 | 16 | die( 'This file is part of a MediaWiki extension, it is not a valid entry point.' ); |
16 | 17 | } |
17 | 18 | |
18 | | -define( 'LINGO_VERSION', '0.1' ); |
19 | | - |
20 | | -$wgExtensionCredits[ 'parserhook' ][ ] = array( |
| 19 | +// Extension credits that will show up on Special:Version |
| 20 | +$wgExtensionCredits['parserhook'][] = array( |
21 | 21 | 'path' => __FILE__, |
22 | 22 | 'name' => 'Lingo', |
| 23 | + 'version' => '0.1', |
23 | 24 | 'author' => 'Barry Coughlan', |
24 | 25 | 'url' => 'http://www.mediawiki.org/wiki/Extension:Lingo', |
25 | 26 | 'description' => 'Provides hover-over tool tips on articles from words defined on the [[Terminology]] page', |
26 | | - 'version' => '0.1' |
27 | 27 | ); |
28 | 28 | |
29 | | -$wgHooks[ 'OutputPageBeforeHTML' ][ ] = 'lingoHook'; |
| 29 | +$wgHooks['OutputPageBeforeHTML'][] = 'lingoHook'; |
30 | 30 | |
31 | | -function lingoHook ( &$out, &$text ) { |
| 31 | +function lingoHook( &$out, &$text ) { |
32 | 32 | global $wgOut, $wgScriptPath; |
33 | | - $out -> includeJQuery(); |
34 | | - $out -> addHeadItem( 'tooltip.css', '<link rel="stylesheet" type="text/css" href="' . $wgScriptPath . '/extensions/Lingo/tooltip.css"/>' ); |
35 | | - $out -> addHeadItem( 'tooltip.js', '<script type="text/javascript" src="' . $wgScriptPath . '/extensions/Lingo/tooltip.min.js"></script>' ); |
| 33 | + $out->includeJQuery(); |
| 34 | + $out->addHeadItem( 'tooltip.css', '<link rel="stylesheet" type="text/css" href="' . $wgScriptPath . '/extensions/Lingo/tooltip.css"/>' ); |
| 35 | + $out->addHeadItem( 'tooltip.js', '<script type="text/javascript" src="' . $wgScriptPath . '/extensions/Lingo/tooltip.min.js"></script>' ); |
36 | 36 | return $out; |
37 | 37 | } |
38 | 38 | |
39 | | -function getLingoArray ( &$content ) { |
40 | | - $term = array( ); |
| 39 | +function getLingoArray( &$content ) { |
| 40 | + $term = array(); |
41 | 41 | $c = explode( "\n", $content ); |
42 | 42 | |
43 | 43 | foreach ( $c as $entry ) { |
44 | | - if ( empty( $entry ) || $entry[ 0 ] !== ';' ) |
| 44 | + if ( empty( $entry ) || $entry[ 0 ] !== ';' ) { |
45 | 45 | continue; |
| 46 | + } |
46 | 47 | |
47 | 48 | $terms = explode( ':', $entry, 2 ); |
48 | | - if ( count( $terms ) < 2 ) |
49 | | - continue; //Invalid syntax |
50 | | - //Add to array |
51 | | - $term[ trim( substr( $terms[ 0 ], 1 ) ) ] = trim( $terms[ 1 ] ); |
| 49 | + if ( count( $terms ) < 2 ) { |
| 50 | + continue; // Invalid syntax |
| 51 | + } |
| 52 | + // Add to array |
| 53 | + $term[trim( substr( $terms[0], 1 ) )] = trim( $terms[1] ); |
52 | 54 | } |
53 | 55 | return $term; |
54 | 56 | } |
55 | 57 | |
56 | | -$wgHooks[ 'ParserAfterTidy' ][ ] = 'lingoParser'; |
| 58 | +$wgHooks['ParserAfterTidy'][] = 'lingoParser'; |
57 | 59 | |
58 | | -function lingoParser ( &$parser, &$text ) { |
| 60 | +function lingoParser( &$parser, &$text ) { |
59 | 61 | global $wgRequest; |
60 | | - $action = $wgRequest -> getVal( 'action', 'view' ); |
61 | | - if ( $action == "edit" || $action == "ajax" || isset( $_POST[ 'wpPreview' ] ) ) |
| 62 | + |
| 63 | + $action = $wgRequest->getVal( 'action', 'view' ); |
| 64 | + if ( $action == 'edit' || $action == 'ajax' || isset( $_POST['wpPreview'] ) ) { |
62 | 65 | return false; |
| 66 | + } |
63 | 67 | |
64 | | - //Get Terminology page |
| 68 | + // Get Terminology page |
65 | 69 | $rev = Revision::newFromTitle( Title::makeTitle( null, 'Terminology' ) ); |
66 | | - if ( !$rev ) |
| 70 | + if ( !$rev ) { |
67 | 71 | return false; |
68 | | - $content = &$rev -> getText(); |
69 | | - if ( empty( $content ) ) |
| 72 | + } |
| 73 | + $content = &$rev->getText(); |
| 74 | + if ( empty( $content ) ) { |
70 | 75 | return false; |
| 76 | + } |
71 | 77 | |
72 | | - //Get array of terms |
| 78 | + // Get array of terms |
73 | 79 | $terms = getLingoArray( $content ); |
74 | | - //Get the minimum length abbreviation so we don't bother checking against words shorter than that |
| 80 | + // Get the minimum length abbreviation so we don't bother checking against words shorter than that |
75 | 81 | $min = min( array_map( 'strlen', array_keys( $terms ) ) ); |
76 | 82 | |
77 | | - //Parse HTML from page |
78 | | - // FIXME: this works in PHP 5.3.3. What about 5.1? |
| 83 | + // Parse HTML from page |
| 84 | + // @todo FIXME: this works in PHP 5.3.3. What about 5.1? |
79 | 85 | wfSuppressWarnings(); |
80 | 86 | $doc = DOMDocument::loadHTML( '<html><meta http-equiv="content-type" content="charset=utf-8"/>' . $text . '</html>' ); |
81 | 87 | wfRestoreWarnings(); |
82 | 88 | |
83 | | - //Find all text in HTML. |
| 89 | + // Find all text in HTML. |
84 | 90 | $xpath = new DOMXpath( $doc ); |
85 | | - $elements = $xpath -> query( "//*[text()!=' ']/text()" ); |
| 91 | + $elements = $xpath->query( "//*[text()!=' ']/text()" ); |
86 | 92 | |
87 | | - //Iterate all HTML text matches |
88 | | - $nb = $elements -> length; |
| 93 | + // Iterate all HTML text matches |
| 94 | + $nb = $elements->length; |
89 | 95 | $changed = false; |
90 | 96 | for ( $pos = 0; $pos < $nb; $pos++ ) { |
91 | | - $el = &$elements -> item( $pos ); |
92 | | - if ( strlen( $el -> nodeValue ) < $min ) |
| 97 | + $el = &$elements->item( $pos ); |
| 98 | + if ( strlen( $el->nodeValue ) < $min ) { |
93 | 99 | continue; |
| 100 | + } |
94 | 101 | |
95 | | - //Split node text into words, putting offset and text into $offsets[0] array |
96 | | - preg_match_all( "/[^\s\.,;:]+/", $el -> nodeValue, $offsets, PREG_OFFSET_CAPTURE ); |
| 102 | + // Split node text into words, putting offset and text into $offsets[0] array |
| 103 | + preg_match_all( |
| 104 | + '/[^\s\.,;:]+/', |
| 105 | + $el->nodeValue, |
| 106 | + $offsets, |
| 107 | + PREG_OFFSET_CAPTURE |
| 108 | + ); |
97 | 109 | |
98 | | - //Search and replace words in reverse order (from end of string backwards), |
99 | | - //This way we don't mess up the offsets of the words as we iterate |
100 | | - $len = count( $offsets[ 0 ] ); |
| 110 | + // Search and replace words in reverse order (from end of string backwards), |
| 111 | + // This way we don't mess up the offsets of the words as we iterate |
| 112 | + $len = count( $offsets[0] ); |
101 | 113 | for ( $i = $len - 1; $i >= 0; $i-- ) { |
102 | | - $offset = $offsets[ 0 ][ $i ]; |
103 | | - //Check if word is an abbreviation from the terminologies |
104 | | - if ( !is_numeric( $offset[ 0 ] ) && isset( $terms[ $offset[ 0 ] ] ) ) { //Word matches, replace with appropriate span tag |
| 114 | + $offset = $offsets[0][$i]; |
| 115 | + // Check if word is an abbreviation from the terminologies |
| 116 | + // Word matches, replace with appropriate span tag |
| 117 | + if ( !is_numeric( $offset[0] ) && isset( $terms[$offset[0]] ) ) { |
105 | 118 | $changed = true; |
106 | 119 | |
107 | | - $tip = htmlentities( $terms[ $offset[ 0 ] ], ENT_COMPAT, 'UTF-8' ); |
| 120 | + $tip = htmlentities( $terms[$offset[0]], ENT_COMPAT, 'UTF-8' ); |
108 | 121 | |
109 | | - $beforeMatchNode = $doc -> createTextNode( substr( $el -> nodeValue, 0, $offset[ 1 ] ) ); |
110 | | - $afterMatchNode = $doc -> createTextNode( substr( $el -> nodeValue, $offset[ 1 ] + strlen( $offset[ 0 ] ), strlen( $el -> nodeValue ) - 1 ) ); |
| 122 | + $beforeMatchNode = $doc->createTextNode( substr( $el->nodeValue, 0, $offset[1] ) ); |
| 123 | + $afterMatchNode = $doc->createTextNode( |
| 124 | + substr( |
| 125 | + $el->nodeValue, |
| 126 | + $offset[1] + strlen( $offset[0] ), |
| 127 | + strlen( $el->nodeValue ) - 1 |
| 128 | + ) |
| 129 | + ); |
111 | 130 | |
112 | | - //Wrap abbreviation in <span> tags |
113 | | - $span = $doc -> createElement( 'span', $offset[ 0 ] ); |
114 | | - $span -> setAttribute( 'class', "tooltip_abbr" ); |
| 131 | + // Wrap abbreviation in <span> tags |
| 132 | + $span = $doc->createElement( 'span', $offset[0] ); |
| 133 | + $span->setAttribute( 'class', 'tooltip_abbr' ); |
115 | 134 | |
116 | | - //Wrap definition in <span> tags, hidden |
117 | | - $spanTip = $doc -> createElement( 'span', $tip ); |
118 | | - $spanTip -> setAttribute( 'class', "tooltip_hide" ); |
| 135 | + // Wrap definition in <span> tags, hidden |
| 136 | + $spanTip = $doc->createElement( 'span', $tip ); |
| 137 | + $spanTip->setAttribute( 'class', 'tooltip_hide' ); |
119 | 138 | |
120 | | - $el -> parentNode -> insertBefore( $beforeMatchNode, $el ); |
121 | | - $el -> parentNode -> insertBefore( $span, $el ); |
122 | | - $span -> appendChild( $spanTip ); |
123 | | - $el -> parentNode -> insertBefore( $afterMatchNode, $el ); |
124 | | - $el -> parentNode -> removeChild( $el ); |
125 | | - $el = $beforeMatchNode; //Set new element to the text before the match for next iteration |
| 139 | + $el->parentNode->insertBefore( $beforeMatchNode, $el ); |
| 140 | + $el->parentNode->insertBefore( $span, $el ); |
| 141 | + $span->appendChild( $spanTip ); |
| 142 | + $el->parentNode->insertBefore( $afterMatchNode, $el ); |
| 143 | + $el->parentNode->removeChild( $el ); |
| 144 | + // Set new element to the text before the match for next iteration |
| 145 | + $el = $beforeMatchNode; |
126 | 146 | } |
127 | 147 | } |
128 | 148 | } |
129 | 149 | |
130 | 150 | if ( $changed ) { |
| 151 | + $body = $xpath->query( '/html/body' ); |
131 | 152 | |
132 | | - $body = $xpath -> query( '/html/body' ); |
133 | | - |
134 | 153 | $text = ''; |
135 | | - foreach ( $body -> item( 0 ) -> childNodes as $child ) { |
136 | | - $text .= $doc -> saveXML( $child ); |
| 154 | + foreach ( $body->item( 0 )->childNodes as $child ) { |
| 155 | + $text .= $doc->saveXML( $child ); |
137 | 156 | } |
138 | | - |
139 | 157 | } |
140 | 158 | |
141 | 159 | return true; |