Index: trunk/extensions/DidYouMean/DidYouMean_body.php |
— | — | @@ -0,0 +1,175 @@ |
| 2 | +<?php
|
| 3 | +/**
|
| 4 | + * Class definition for DidYouMean functions
|
| 5 | + */
|
| 6 | +class DidYouMean {
|
| 7 | +
|
| 8 | + # turn the array of titles into some wikitext we can add to an article
|
| 9 | +
|
| 10 | + public static function build_sees( $sees ) {
|
| 11 | + global $wgDymUseSeeTemplate;
|
| 12 | +
|
| 13 | + if ( $wgDymUseSeeTemplate )
|
| 14 | + return '{{see|' . implode('|', $sees) . '}}';
|
| 15 | + else
|
| 16 | + return '<div>\'\'See also:\'\' \'\'\'[[' . implode(']]\'\'\', \'\'\'[[', $sees) . ']]\'\'\'</div>';
|
| 17 | + }
|
| 18 | +
|
| 19 | + # pass pageid = 0 to lookup by normtitle
|
| 20 | + public static function lookup( $pageid, $title ) {
|
| 21 | + wfDebug( 'HIPP: ' . __METHOD__ . "\n" );
|
| 22 | +
|
| 23 | + $sees = array();
|
| 24 | +
|
| 25 | + $dbr = wfGetDB( DB_SLAVE );
|
| 26 | +
|
| 27 | + if ( $dbr->tableExists( 'dympage' ) && $dbr->tableExists( 'dymnorm' ) ) {
|
| 28 | + $normid = false;
|
| 29 | +
|
| 30 | + if ($pageid) {
|
| 31 | + wfDebug( "HIPP: lookup by pageid: $pageid\n" );
|
| 32 | + $normid = $dbr->selectField(
|
| 33 | + array( 'page', 'dympage' ),
|
| 34 | + 'dp_normid',
|
| 35 | + array( 'page_id = dp_pageid', 'page_id' => $pageid )
|
| 36 | + );
|
| 37 | + } else {
|
| 38 | + wfDebug( "HIPP: lookup by normtitle: " . wfDymNormalise($title) . "\n" );
|
| 39 | + $normid = $dbr->selectField(
|
| 40 | + 'dymnorm',
|
| 41 | + 'dn_normid',
|
| 42 | + array( 'dn_normtitle' => wfDymNormalise($title) )
|
| 43 | + );
|
| 44 | + }
|
| 45 | +
|
| 46 | + if ($normid) {
|
| 47 | + $res = $dbr->select(
|
| 48 | + /* FROM */ array( 'page', 'dympage' ),
|
| 49 | + /* SELECT */ 'page_title',
|
| 50 | + /* WHERE */ array( 'page_id = dp_pageid', 'dp_normid' => $normid )
|
| 51 | + );
|
| 52 | +
|
| 53 | + $nr = $dbr->numRows( $res );
|
| 54 | +
|
| 55 | + if ($nr == 0) {
|
| 56 | + wfDebug( "HIPP: DB New Miss\n" );
|
| 57 | + } else {
|
| 58 | + wfDebug( "HIPP: DB New Hit\n" );
|
| 59 | +
|
| 60 | + # accumulate the db results
|
| 61 | + while( $o = $dbr->fetchObject( $res ) ) {
|
| 62 | + $t2 = str_replace('_', ' ', $o->page_title);
|
| 63 | + $dbo = $t2;
|
| 64 | + if ($title != $t2) {
|
| 65 | + array_push( $sees, $t2 );
|
| 66 | + $dbo = '++ ' . $dbo;
|
| 67 | + }
|
| 68 | + else
|
| 69 | + $dbo = ' (' . $dbo . ')';
|
| 70 | + wfDebug( "HIPP: $dbo\n" );
|
| 71 | + }
|
| 72 | +
|
| 73 | + $dbr->freeResult( $res );
|
| 74 | + }
|
| 75 | + }
|
| 76 | + } else {
|
| 77 | + wfDebug( "HIPP: No dympage or dymnorm table\n" );
|
| 78 | + }
|
| 79 | +
|
| 80 | + return $sees;
|
| 81 | + }
|
| 82 | +
|
| 83 | + public static function doInsert( $pageid , $title ) {
|
| 84 | + wfDebug( 'HIPP: ' . __METHOD__ . " INSERT\n" );
|
| 85 | + $dbw = wfGetDB( DB_MASTER );
|
| 86 | +
|
| 87 | + $norm = wfDymNormalise($title);
|
| 88 | +
|
| 89 | + # find or create normid for the new title
|
| 90 | + $normid = $dbw->selectField( 'dymnorm', 'dn_normid', array( 'dn_normtitle' => $norm ) );
|
| 91 | + if ($normid) {
|
| 92 | + wfDebug( "HIPP: old: $title ->\t$norm = $normid\n" );
|
| 93 | + } else {
|
| 94 | + $nsvid = $dbw->nextSequenceValue( 'dymnorm_dn_normid_seq' );
|
| 95 | + $dbw->insert( 'dymnorm', array( 'dn_normid' => $nsvid, 'dn_normtitle' => $norm ) );
|
| 96 | + $normid = $dbw->insertId();
|
| 97 | + wfDebug( "HIPP: NEW: $title ->\t$norm = $normid\n" );
|
| 98 | + }
|
| 99 | + $dbw->insert( 'dympage', array( 'dp_pageid' => $pageid, 'dp_normid' => $normid ) );
|
| 100 | +
|
| 101 | + # touch all pages which will now link here
|
| 102 | + self::touchPages( "dp_normid=$normid" );
|
| 103 | +
|
| 104 | + }
|
| 105 | +
|
| 106 | + private static function touchPages( $condition ) {
|
| 107 | + global $wgDBtype;
|
| 108 | +
|
| 109 | + $dbw = wfGetDB( DB_MASTER );
|
| 110 | + $page = $dbw->tableName('page');
|
| 111 | + $dpage = $dbw->tableName('dympage');
|
| 112 | +
|
| 113 | + $whereclause = "WHERE page_id = dp_pageid AND $condition";
|
| 114 | + if ($wgDBtype == 'postgres') {
|
| 115 | + $sql = "UPDATE $page SET page_touched=now() FROM $dpage $whereclause";
|
| 116 | + } else {
|
| 117 | + $sql = "UPDATE $page, $dpage SET page_touched = " .
|
| 118 | + $dbw->addQuotes( $dbw->timestamp() ) .
|
| 119 | + " $whereclause";
|
| 120 | + }
|
| 121 | +
|
| 122 | + $dbw->query( $sql, __METHOD__ );
|
| 123 | +
|
| 124 | + }
|
| 125 | +
|
| 126 | + public static function doDelete( $pageid ) {
|
| 127 | + wfDebug( 'HIPP: ' . __METHOD__ . " DELETE\n" );
|
| 128 | + $dbw = wfGetDB( DB_MASTER );
|
| 129 | +
|
| 130 | + $normid = $dbw->selectField( 'dympage', 'dp_normid', array('dp_pageid' => $pageid) );
|
| 131 | +
|
| 132 | + $dbw->delete( 'dympage', array('dp_pageid' => $pageid) );
|
| 133 | +
|
| 134 | + $count = $dbw->selectField( 'dympage', 'COUNT(*)', array('dp_normid' => $normid) );
|
| 135 | +
|
| 136 | + if ($count == 0)
|
| 137 | + $dbw->delete( 'dymnorm', array('dn_normid' => $normid) );
|
| 138 | +
|
| 139 | + # touch all pages which will now link here
|
| 140 | + if( $normid ) {
|
| 141 | + self::touchPages( "dp_normid=$normid" );
|
| 142 | + }
|
| 143 | + }
|
| 144 | +
|
| 145 | + public static function doUpdate( $pageid, $title ) {
|
| 146 | + wfDebug( 'HIPP: ' . __METHOD__ . " MOVE\n" );
|
| 147 | + $dbw = wfGetDB( DB_MASTER );
|
| 148 | +
|
| 149 | + $norm = wfDymNormalise($title);
|
| 150 | +
|
| 151 | + $normid = $dbw->selectField( 'dymnorm', 'dn_normid', array( 'dn_normtitle' => $norm ) );
|
| 152 | + if ($normid) {
|
| 153 | + wfDebug( "HIPP: old: $title ->\t$norm = $normid\n" );
|
| 154 | + } else {
|
| 155 | + $nsvid = $dbw->nextSequenceValue( 'dymnorm_dn_normid_seq' );
|
| 156 | + $dbw->insert( 'dymnorm', array( 'dn_normid' => $nsvid, 'dn_normtitle' => $norm ) );
|
| 157 | + $normid = $dbw->insertId();
|
| 158 | + wfDebug( "HIPP: NEW: $title ->\t$norm = $normid\n" );
|
| 159 | + }
|
| 160 | +
|
| 161 | + $oldnormid = $dbw->selectField( 'dympage', 'dp_normid', array('dp_pageid' => $pageid) );
|
| 162 | +
|
| 163 | + if ($oldnormid != $normid) {
|
| 164 | + $dbw->update( 'dympage', array( 'dp_normid' => $normid ), array( 'dp_pageid' => $pageid ) );
|
| 165 | +
|
| 166 | + $count = $dbw->selectField( 'dympage', 'COUNT(*)', array('dp_normid' => $oldnormid) );
|
| 167 | +
|
| 168 | + if ($count == 0)
|
| 169 | + $dbw->delete( 'dymnorm', array('dn_normid' => $oldnormid) );
|
| 170 | +
|
| 171 | + # touch all pages which linked to the old name or will link to the new one
|
| 172 | + self::touchPages( "(dp_normid=$normid OR dp_normid=$oldnormid)" );
|
| 173 | +
|
| 174 | + }
|
| 175 | + }
|
| 176 | +} |
\ No newline at end of file |
Index: trunk/extensions/DidYouMean/DidYouMean.php |
— | — | @@ -9,411 +9,38 @@ |
10 | 10 | $wgExtensionCredits['other'][] = array( |
11 | 11 | 'path' => __FILE__, |
12 | 12 | 'name' => 'DidYouMean', |
13 | | - 'author' => 'hippietrail (Andrew Dunbar)', |
| 13 | + 'author' => array( 'hippietrail (Andrew Dunbar)', 'Chad Horohoe' ), |
14 | 14 | 'url' => 'http://www.mediawiki.org/wiki/Extension:DidYouMean', |
15 | 15 | 'descriptionmsg' => 'didyoumean-desc', |
16 | 16 | ); |
17 | | -$wgExtensionMessagesFiles['DidYouMean'] = dirname(__FILE__) . '/DidYouMean.i18n.php'; |
| 17 | +$dir = dirname(__FILE__) . '/' |
| 18 | +$wgExtensionMessagesFiles['DidYouMean'] = $dir . 'DidYouMean.i18n.php'; |
| 19 | +$wgAutoloadClasses['DidYouMeanHooks'] = $dir . 'DidYouMean.hooks.php'; |
| 20 | +$wgAutoloadClasses['DidYouMean'] = $dir . 'DidYouMean_body.php'; |
18 | 21 | |
19 | 22 | # do database lookup from these |
20 | | -$wgHooks['ArticleNoArticleText'][] = 'wfDymArticleNoArticleText'; |
21 | | -$wgHooks['SpecialSearchResults'][] = 'wfDymSpecialSearchNoResults'; |
22 | | -$wgHooks['SpecialSearchNoResults'][] = 'wfDymSpecialSearchNoResults'; |
| 23 | +$wgHooks['ArticleNoArticleText'][] = 'DidYouMeanHooks::articleNoArticleText'; |
| 24 | +$wgHooks['SpecialSearchResults'][] = 'DidYouMeanHooks::specialSearchNoResults'; |
| 25 | +$wgHooks['SpecialSearchNoResults'][] = 'DidYouMeanHooks::specialSearchNoResults'; |
23 | 26 | |
24 | 27 | # db lookup + parse existing {{see}} and add enhanced one with db results |
25 | | -$wgHooks['ParserBeforeStrip'][] = 'wfDymParserBeforeStrip'; |
| 28 | +$wgHooks['ParserBeforeStrip'][] = 'DidYouMeanHooks::parserBeforeStrip'; |
26 | 29 | |
27 | 30 | # handle delete |
28 | | -$wgHooks['ArticleDelete'][] = 'wfDymArticleDelete'; |
| 31 | +$wgHooks['ArticleDelete'][] = 'DidYouMeanHooks::articleDelete'; |
29 | 32 | |
30 | 33 | # handle move |
31 | | -$wgHooks['TitleMoveComplete'][] = 'wfDymTitleMoveComplete'; |
| 34 | +$wgHooks['TitleMoveComplete'][] = 'DidYouMeanHooks::titleMoveComplete'; |
32 | 35 | |
33 | 36 | # handle create / edit |
34 | | -$wgHooks['AlternateEdit'][] = 'wfDymAlternateEdit'; |
35 | | -$wgHooks['ArticleSaveComplete'][] = 'wfDymArticleSaveComplete'; |
| 37 | +$wgHooks['AlternateEdit'][] = 'DidYouMeanHooks::alternateEdit'; |
| 38 | +$wgHooks['ArticleSaveComplete'][] = 'DidYouMeanHooks::articleSaveComplete'; |
36 | 39 | |
37 | 40 | # handle undelete |
38 | | -$wgHooks['ArticleUndelete'][] = 'wfDymArticleUndelete'; |
| 41 | +$wgHooks['ArticleUndelete'][] = 'DidYouMeanHooks::articleUndelete'; |
39 | 42 | |
40 | 43 | # handle parser test setup |
41 | | -$wgHooks['ParserTestTables'][] = 'wfDymParserTestTables'; |
| 44 | +$wgHooks['ParserTestTables'][] = 'DidYouMeanHooks::parserTestTables'; |
42 | 45 | |
43 | 46 | # set this in LocalSettings.php |
44 | 47 | $wgDymUseSeeTemplate = false; |
45 | | - |
46 | | -# TODO this is called even when editing a new page |
47 | | - |
48 | | -function wfDymArticleNoArticleText( &$article, &$text ) { |
49 | | - wfDebug( 'HIPP: ' . __METHOD__ . "\n" ); |
50 | | - |
51 | | - $sees = wfDymLookup( 0, $article->getTitle()->getText() ); |
52 | | - |
53 | | - sort($sees); |
54 | | - |
55 | | - if (count($sees)) |
56 | | - $text = build_sees($sees) . $text; |
57 | | - |
58 | | - return true; |
59 | | -} |
60 | | - |
61 | | -# this is called when using the Go/Search box but it is not called when entering |
62 | | -# a URL for a non-existing article |
63 | | - |
64 | | -function wfDymSpecialSearchNoResults( $term ) { |
65 | | - global $wgOut; |
66 | | - |
67 | | - wfDebug( 'HIPP: ' . __METHOD__ . "\n" ); |
68 | | - |
69 | | - $sees = wfDymLookup( 0, $term ); |
70 | | - |
71 | | - sort($sees); |
72 | | - |
73 | | - if (count($sees)) |
74 | | - $wgOut->addWikiText( build_sees($sees) ); |
75 | | - |
76 | | - return true; |
77 | | -} |
78 | | - |
79 | | -# this is called per chunk of wikitext, not per article |
80 | | - |
81 | | -function wfDymParserBeforeStrip( &$parser, &$text, &$stripState ) { |
82 | | - #wfDebug( 'HIPP: ' . __METHOD__ . "\n" ); |
83 | | - |
84 | | - # if revisionid is 0 this is not an article chunk |
85 | | - if( isset( $parser->mDymFirstChunk ) || !$parser->getVariableValue('revisionid') || $parser->getVariableValue('namespace')) |
86 | | - return true; |
87 | | - |
88 | | - $parser->mDymFirstChunk = 'done'; |
89 | | - |
90 | | - $title = $parser->getTitle(); |
91 | | - $parser->mDymSees = wfDymLookup( $title->getArticleID(), $title->getText() ); |
92 | | - |
93 | | - if (preg_match( "/{{[sS]ee\|([^}]*)}}/", $text, $see )) { |
94 | | - wfDebug( "HIPP: see Hit\n" ); |
95 | | - $hasTemplate = true; |
96 | | - $sees = explode("|", $see[1]); |
97 | | - } elseif (preg_match( "/{{[xX]see(\|[^}]*)}}/", $text, $see )) { |
98 | | - wfDebug( "HIPP: xsee Hit\n" ); |
99 | | - $hasTemplate = true; |
100 | | - preg_match_all( "/\|\[\[([^]|]*)(?:\|([^|]*))?\]\](?: \(([^)]*)\))?/", $see[1], $ma ); |
101 | | - $sees = $ma[1]; |
102 | | - } else { |
103 | | - wfDebug( "HIPP: (x)see Miss\n" ); |
104 | | - # there's no {{see}} in this chunk of wikitext |
105 | | - # if this is the 1st chunk of the article itself we can put an empty {{see}} there. |
106 | | - $hasTemplate = false; |
107 | | - $sees = array(); |
108 | | - } |
109 | | - |
110 | | - # normalize entities and urlencoding to pure utf-8 |
111 | | - foreach ($sees as &$value) |
112 | | - $value = rawurldecode(html_entity_decode($value, ENT_QUOTES, 'UTF-8')); |
113 | | - |
114 | | - wfDebug( 'HIPP: Parser: ' . implode(', ', $sees) . "\n" ); |
115 | | - wfDebug( 'HIPP: DBase: ' . implode(', ', $parser->mDymSees) . "\n" ); |
116 | | - |
117 | | - # add in the stuff from the database lookup |
118 | | - $sees = array_unique(array_merge($sees, $parser->mDymSees)); |
119 | | - sort($sees); |
120 | | - |
121 | | - wfDebug( 'HIPP: Merged: ' . implode(', ', $sees) . "\n" ); |
122 | | - |
123 | | - # TODO is it better to use $parser->insertStripItem() ? |
124 | | - |
125 | | - if (count($sees)) { |
126 | | - if( !$hasTemplate ) { |
127 | | - // We need to squish in a fresh copy of the template... |
128 | | - $text = "{{see|}}\n" . $text; |
129 | | - } |
130 | | - $built_sees = build_sees($sees); |
131 | | - } else { |
132 | | - $built_sees = ''; |
133 | | - } |
134 | | - |
135 | | - $text = preg_replace( |
136 | | - '/{{[xX]?[sS]ee\|[^}]*}}/', |
137 | | - #$built_sees . '<div style="text-decoration:line-through">$0</div>', |
138 | | - $built_sees, |
139 | | - $text ); |
140 | | - |
141 | | - return true; |
142 | | -} |
143 | | - |
144 | | -# turn the array of titles into some wikitext we can add to an article |
145 | | - |
146 | | -function build_sees( $sees ) { |
147 | | - global $wgDymUseSeeTemplate; |
148 | | - |
149 | | - if ($wgDymUseSeeTemplate == true) |
150 | | - return '{{see|' . implode('|', $sees) . '}}'; |
151 | | - else |
152 | | - return '<div>\'\'See also:\'\' \'\'\'[[' . implode(']]\'\'\', \'\'\'[[', $sees) . ']]\'\'\'</div>'; |
153 | | -} |
154 | | - |
155 | | -# pass pageid = 0 to lookup by normtitle |
156 | | - |
157 | | -function wfDymLookup( $pageid, $title ) { |
158 | | - wfDebug( 'HIPP: ' . __METHOD__ . "\n" ); |
159 | | - |
160 | | - $sees = array(); |
161 | | - |
162 | | - $dbr = wfGetDB( DB_SLAVE ); |
163 | | - |
164 | | - if ( $dbr->tableExists( 'dympage' ) && $dbr->tableExists( 'dymnorm' ) ) { |
165 | | - $normid = false; |
166 | | - |
167 | | - if ($pageid) { |
168 | | - wfDebug( "HIPP: lookup by pageid: $pageid\n" ); |
169 | | - $normid = $dbr->selectField( |
170 | | - array( 'page', 'dympage' ), |
171 | | - 'dp_normid', |
172 | | - array( 'page_id = dp_pageid', 'page_id' => $pageid ) |
173 | | - ); |
174 | | - } else { |
175 | | - wfDebug( "HIPP: lookup by normtitle: " . wfDymNormalise($title) . "\n" ); |
176 | | - $normid = $dbr->selectField( |
177 | | - 'dymnorm', |
178 | | - 'dn_normid', |
179 | | - array( 'dn_normtitle' => wfDymNormalise($title) ) |
180 | | - ); |
181 | | - } |
182 | | - |
183 | | - if ($normid) { |
184 | | - $res = $dbr->select( |
185 | | - /* FROM */ array( 'page', 'dympage' ), |
186 | | - /* SELECT */ 'page_title', |
187 | | - /* WHERE */ array( 'page_id = dp_pageid', 'dp_normid' => $normid ) |
188 | | - ); |
189 | | - |
190 | | - $nr = $dbr->numRows( $res ); |
191 | | - |
192 | | - if ($nr == 0) { |
193 | | - wfDebug( "HIPP: DB New Miss\n" ); |
194 | | - } else { |
195 | | - wfDebug( "HIPP: DB New Hit\n" ); |
196 | | - |
197 | | - # accumulate the db results |
198 | | - while( $o = $dbr->fetchObject( $res ) ) { |
199 | | - $t2 = str_replace('_', ' ', $o->page_title); |
200 | | - $dbo = $t2; |
201 | | - if ($title != $t2) { |
202 | | - array_push( $sees, $t2 ); |
203 | | - $dbo = '++ ' . $dbo; |
204 | | - } |
205 | | - else |
206 | | - $dbo = ' (' . $dbo . ')'; |
207 | | - wfDebug( "HIPP: $dbo\n" ); |
208 | | - } |
209 | | - |
210 | | - $dbr->freeResult( $res ); |
211 | | - } |
212 | | - } |
213 | | - } else { |
214 | | - wfDebug( "HIPP: No dympage or dymnorm table\n" ); |
215 | | - } |
216 | | - |
217 | | - return $sees; |
218 | | -} |
219 | | - |
220 | | -function wfDymArticleInsertComplete( &$article, &$user, $text, $summary, $isminor, $watchthis, $something ) { |
221 | | - |
222 | | - if ($article->getTitle()->getNamespace() != 0 || $article->isRedirect() == true) |
223 | | - return true; |
224 | | - |
225 | | - wfDymDoInsert( $article->getID(), $article->getTitle()->getText() ); |
226 | | - |
227 | | - return true; |
228 | | -} |
229 | | - |
230 | | -function wfDymArticleUndelete( &$title, &$create ) { |
231 | | - |
232 | | - if ($create == false || $title->getNamespace() != 0) |
233 | | - return true; |
234 | | - |
235 | | - # TODO it's not possible to detect if the undeleted article is a redirect! |
236 | | - #$artic1e = new Article( $title ); |
237 | | - #if ($article->isRedirect( $article->getContent() )) { |
238 | | - # return true; |
239 | | - #} |
240 | | - |
241 | | - wfDymDoInsert( $title->getArticleId(), $title->getText() ); |
242 | | - |
243 | | - return true; |
244 | | -} |
245 | | - |
246 | | -function wfDymArticleDelete( $article, $user, $reason ) { |
247 | | - |
248 | | - if ($article->getTitle()->getNamespace() != 0 || $article->isRedirect() == true) |
249 | | - return true; |
250 | | - |
251 | | - wfDymDoDelete( $article->getID() ); |
252 | | - |
253 | | - return true; |
254 | | -} |
255 | | - |
256 | | -function wfDymTitleMoveComplete( &$title, &$nt, &$wgUser, &$pageid, &$redirid ) { |
257 | | - $oldtitletext = $title->getText(); |
258 | | - $oldns = $title->getNamespace(); |
259 | | - $newtitletext = $nt->getText(); |
260 | | - $newns = $nt->getNamespace(); |
261 | | - |
262 | | - wfDebug( 'HIPP: ' . __METHOD__ . "\n" ); |
263 | | - |
264 | | - if ($oldns != 0 && $newns != 0) |
265 | | - return true; |
266 | | - |
267 | | - # TODO we can't always check if we're moving a redirect because the old article's content |
268 | | - # TODO has already been replaced with the redirect to the new title but a |
269 | | - # TODO new title's content is still "noarticletext" at this point! |
270 | | - #$a1 = new Article( $title ); |
271 | | - #$a2 = new Article( $nt ); |
272 | | - #wfDebug( "HIPP: getContent() for isRedirect()\n\tfrom <<<" . $a1->getContent() . ">>>\n\t to <<<" . $a2->getContent() . ">>>\n" ); |
273 | | - #if ($a1->isRedirect( $a->getContent() )) { |
274 | | - # wfDebug( "HIPP: moving a redirect (?)\n" ); |
275 | | - # return true; |
276 | | - #} |
277 | | - |
278 | | - if ($oldns == 0 && $newns == 0) { |
279 | | - wfDymDoUpdate( $pageid, $newtitletext ); |
280 | | - } elseif ($oldns == 0) { |
281 | | - wfDymDoDelete( $pageid ); |
282 | | - } elseif ($newns == 0) { |
283 | | - wfDymDoInsert( $pageid, $newtitletext ); |
284 | | - } |
285 | | - |
286 | | - return true; |
287 | | -} |
288 | | - |
289 | | -# called at action=edit. can detect if we're about to edit a redirect |
290 | | - |
291 | | -function wfDymAlternateEdit( $editpage ) { |
292 | | - global $wgParser; |
293 | | - |
294 | | - if ($editpage->mArticle->isRedirect()) |
295 | | - $wgParser->mDymRedirBeforeEdit = true; |
296 | | - |
297 | | - return 1; |
298 | | -} |
299 | | - |
300 | | -# called at end of action=submit |
301 | | - |
302 | | -function wfDymArticleSaveComplete( $article, $user, $text, $summary, $isminor, $dunno1, $dunno2, $flags ) { |
303 | | - global $wgParser; |
304 | | - |
305 | | - if ($article->getTitle()->getNamespace() != 0) |
306 | | - return true; |
307 | | - |
308 | | - if ($article->isRedirect($text)) { |
309 | | - if (empty( $wgParser->mDymRedirBeforeEdit ) && !($flags & EDIT_NEW)) |
310 | | - wfDymDoDelete( $article->getID() ); |
311 | | - } else { |
312 | | - if (!empty( $wgParser->mDymRedirBeforeEdit ) || $flags & EDIT_NEW) |
313 | | - wfDymDoInsert( $article->getID(), $article->getTitle()->getText() ); |
314 | | - } |
315 | | - |
316 | | - $wgParser->mDymRedirBeforeEdit = false; |
317 | | - |
318 | | - return true; |
319 | | -} |
320 | | - |
321 | | -function wfDymDoInsert( $pageid , $title ) { |
322 | | - wfDebug( 'HIPP: ' . __METHOD__ . " INSERT\n" ); |
323 | | - $dbw = wfGetDB( DB_MASTER ); |
324 | | - |
325 | | - $norm = wfDymNormalise($title); |
326 | | - |
327 | | - # find or create normid for the new title |
328 | | - $normid = $dbw->selectField( 'dymnorm', 'dn_normid', array( 'dn_normtitle' => $norm ) ); |
329 | | - if ($normid) { |
330 | | - wfDebug( "HIPP: old: $title ->\t$norm = $normid\n" ); |
331 | | - } else { |
332 | | - $nsvid = $dbw->nextSequenceValue( 'dymnorm_dn_normid_seq' ); |
333 | | - $dbw->insert( 'dymnorm', array( 'dn_normid' => $nsvid, 'dn_normtitle' => $norm ) ); |
334 | | - $normid = $dbw->insertId(); |
335 | | - wfDebug( "HIPP: NEW: $title ->\t$norm = $normid\n" ); |
336 | | - } |
337 | | - $dbw->insert( 'dympage', array( 'dp_pageid' => $pageid, 'dp_normid' => $normid ) ); |
338 | | - |
339 | | - # touch all pages which will now link here |
340 | | - wfDymTouchPages( "dp_normid=$normid" ); |
341 | | - |
342 | | -} |
343 | | - |
344 | | - |
345 | | -function wfDymTouchPages( $condition ) { |
346 | | - global $wgDBtype; |
347 | | - |
348 | | - $dbw = wfGetDB( DB_MASTER ); |
349 | | - $page = $dbw->tableName('page'); |
350 | | - $dpage = $dbw->tableName('dympage'); |
351 | | - |
352 | | - $whereclause = "WHERE page_id = dp_pageid AND $condition"; |
353 | | - if ($wgDBtype == 'postgres') { |
354 | | - $sql = "UPDATE $page SET page_touched=now() FROM $dpage $whereclause"; |
355 | | - } else { |
356 | | - $sql = "UPDATE $page, $dpage SET page_touched = " . |
357 | | - $dbw->addQuotes( $dbw->timestamp() ) . |
358 | | - " $whereclause"; |
359 | | - } |
360 | | - |
361 | | - $dbw->query( $sql, __METHOD__ ); |
362 | | - |
363 | | -} |
364 | | - |
365 | | -function wfDymDoDelete( $pageid ) { |
366 | | - wfDebug( 'HIPP: ' . __METHOD__ . " DELETE\n" ); |
367 | | - $dbw = wfGetDB( DB_MASTER ); |
368 | | - |
369 | | - $normid = $dbw->selectField( 'dympage', 'dp_normid', array('dp_pageid' => $pageid) ); |
370 | | - |
371 | | - $dbw->delete( 'dympage', array('dp_pageid' => $pageid) ); |
372 | | - |
373 | | - $count = $dbw->selectField( 'dympage', 'COUNT(*)', array('dp_normid' => $normid) ); |
374 | | - |
375 | | - if ($count == 0) |
376 | | - $dbw->delete( 'dymnorm', array('dn_normid' => $normid) ); |
377 | | - |
378 | | - # touch all pages which will now link here |
379 | | - if( $normid ) { |
380 | | - wfDymTouchPages( "dp_normid=$normid" ); |
381 | | - } |
382 | | -} |
383 | | - |
384 | | -function wfDymDoUpdate( $pageid, $title ) { |
385 | | - wfDebug( 'HIPP: ' . __METHOD__ . " MOVE\n" ); |
386 | | - $dbw = wfGetDB( DB_MASTER ); |
387 | | - |
388 | | - $norm = wfDymNormalise($title); |
389 | | - |
390 | | - $normid = $dbw->selectField( 'dymnorm', 'dn_normid', array( 'dn_normtitle' => $norm ) ); |
391 | | - if ($normid) { |
392 | | - wfDebug( "HIPP: old: $title ->\t$norm = $normid\n" ); |
393 | | - } else { |
394 | | - $nsvid = $dbw->nextSequenceValue( 'dymnorm_dn_normid_seq' ); |
395 | | - $dbw->insert( 'dymnorm', array( 'dn_normid' => $nsvid, 'dn_normtitle' => $norm ) ); |
396 | | - $normid = $dbw->insertId(); |
397 | | - wfDebug( "HIPP: NEW: $title ->\t$norm = $normid\n" ); |
398 | | - } |
399 | | - |
400 | | - $oldnormid = $dbw->selectField( 'dympage', 'dp_normid', array('dp_pageid' => $pageid) ); |
401 | | - |
402 | | - if ($oldnormid != $normid) { |
403 | | - $dbw->update( 'dympage', array( 'dp_normid' => $normid ), array( 'dp_pageid' => $pageid ) ); |
404 | | - |
405 | | - $count = $dbw->selectField( 'dympage', 'COUNT(*)', array('dp_normid' => $oldnormid) ); |
406 | | - |
407 | | - if ($count == 0) |
408 | | - $dbw->delete( 'dymnorm', array('dn_normid' => $oldnormid) ); |
409 | | - |
410 | | - # touch all pages which linked to the old name or will link to the new one |
411 | | - wfDymTouchPages( "(dp_normid=$normid OR dp_normid=$oldnormid)" ); |
412 | | - |
413 | | - } |
414 | | -} |
415 | | - |
416 | | -function wfDymParserTestTables( &$tables ) { |
417 | | - $tables[] = 'dympage'; |
418 | | - $tables[] = 'dymnorm'; |
419 | | - return true; |
420 | | -} |
Index: trunk/extensions/DidYouMean/DidYouMean.hooks.php |
— | — | @@ -0,0 +1,194 @@ |
| 2 | +<?php
|
| 3 | +/**
|
| 4 | + * All the hooks for DidYouMean
|
| 5 | + */
|
| 6 | +class DidYouMeanHooks {
|
| 7 | +
|
| 8 | + # TODO this is called even when editing a new page
|
| 9 | + public static function articleNoArticleText( &$article, &$text ) {
|
| 10 | + wfDebug( 'HIPP: ' . __METHOD__ . "\n" );
|
| 11 | +
|
| 12 | + $sees = DidYouMean::lookup( 0, $article->getTitle()->getText() );
|
| 13 | +
|
| 14 | + sort($sees);
|
| 15 | +
|
| 16 | + if (count($sees))
|
| 17 | + $text = DidYouMean::build_sees($sees) . $text;
|
| 18 | +
|
| 19 | + return true;
|
| 20 | + }
|
| 21 | +
|
| 22 | + # this is called when using the Go/Search box but it is not called when entering
|
| 23 | + # a URL for a non-existing article
|
| 24 | + public static function specialSearchNoResults( $term ) {
|
| 25 | + wfDebug( 'HIPP: ' . __METHOD__ . "\n" );
|
| 26 | +
|
| 27 | + $sees = DidYouMean::lookup( 0, $term );
|
| 28 | +
|
| 29 | + sort($sees);
|
| 30 | +
|
| 31 | + if ( count($sees) ) {
|
| 32 | + global $wgOut;
|
| 33 | + $wgOut->addWikiText( DidYouMean::build_sees($sees) );
|
| 34 | + }
|
| 35 | + return true;
|
| 36 | + }
|
| 37 | +
|
| 38 | + # this is called per chunk of wikitext, not per article
|
| 39 | + public static function parserBeforeStrip( &$parser, &$text, &$stripState ) {
|
| 40 | + #wfDebug( 'HIPP: ' . __METHOD__ . "\n" );
|
| 41 | +
|
| 42 | + # if revisionid is 0 this is not an article chunk
|
| 43 | + if( isset( $parser->mDymFirstChunk ) || !$parser->getVariableValue('revisionid') || $parser->getVariableValue('namespace'))
|
| 44 | + return true;
|
| 45 | +
|
| 46 | + $parser->mDymFirstChunk = 'done';
|
| 47 | +
|
| 48 | + $title = $parser->getTitle();
|
| 49 | + $parser->mDymSees = DidYouMean::lookup( $title->getArticleID(), $title->getText() );
|
| 50 | +
|
| 51 | + if (preg_match( "/{{[sS]ee\|([^}]*)}}/", $text, $see )) {
|
| 52 | + wfDebug( "HIPP: see Hit\n" );
|
| 53 | + $hasTemplate = true;
|
| 54 | + $sees = explode("|", $see[1]);
|
| 55 | + } elseif (preg_match( "/{{[xX]see(\|[^}]*)}}/", $text, $see )) {
|
| 56 | + wfDebug( "HIPP: xsee Hit\n" );
|
| 57 | + $hasTemplate = true;
|
| 58 | + preg_match_all( "/\|\[\[([^]|]*)(?:\|([^|]*))?\]\](?: \(([^)]*)\))?/", $see[1], $ma );
|
| 59 | + $sees = $ma[1];
|
| 60 | + } else {
|
| 61 | + wfDebug( "HIPP: (x)see Miss\n" );
|
| 62 | + # there's no {{see}} in this chunk of wikitext
|
| 63 | + # if this is the 1st chunk of the article itself we can put an empty {{see}} there.
|
| 64 | + $hasTemplate = false;
|
| 65 | + $sees = array();
|
| 66 | + }
|
| 67 | +
|
| 68 | + # normalize entities and urlencoding to pure utf-8
|
| 69 | + foreach ($sees as &$value)
|
| 70 | + $value = rawurldecode(html_entity_decode($value, ENT_QUOTES, 'UTF-8'));
|
| 71 | +
|
| 72 | + wfDebug( 'HIPP: Parser: ' . implode(', ', $sees) . "\n" );
|
| 73 | + wfDebug( 'HIPP: DBase: ' . implode(', ', $parser->mDymSees) . "\n" );
|
| 74 | +
|
| 75 | + # add in the stuff from the database lookup
|
| 76 | + $sees = array_unique(array_merge($sees, $parser->mDymSees));
|
| 77 | + sort($sees);
|
| 78 | +
|
| 79 | + wfDebug( 'HIPP: Merged: ' . implode(', ', $sees) . "\n" );
|
| 80 | +
|
| 81 | + # TODO is it better to use $parser->insertStripItem() ?
|
| 82 | +
|
| 83 | + if (count($sees)) {
|
| 84 | + if( !$hasTemplate ) {
|
| 85 | + // We need to squish in a fresh copy of the template...
|
| 86 | + $text = "{{see|}}\n" . $text;
|
| 87 | + }
|
| 88 | + $built_sees = DidYouMean::build_sees($sees);
|
| 89 | + } else {
|
| 90 | + $built_sees = '';
|
| 91 | + }
|
| 92 | +
|
| 93 | + $text = preg_replace(
|
| 94 | + '/{{[xX]?[sS]ee\|[^}]*}}/',
|
| 95 | + #$built_sees . '<div style="text-decoration:line-through">$0</div>',
|
| 96 | + $built_sees,
|
| 97 | + $text );
|
| 98 | +
|
| 99 | + return true;
|
| 100 | + }
|
| 101 | +
|
| 102 | + public static function articleDelete( $article, $user, $reason ) {
|
| 103 | + if ($article->getTitle()->getNamespace() != 0 || $article->isRedirect() == true)
|
| 104 | + return true;
|
| 105 | +
|
| 106 | + DidYouMean::doDelete( $article->getID() );
|
| 107 | +
|
| 108 | + return true;
|
| 109 | + }
|
| 110 | +
|
| 111 | + public static function titleMoveComplete( &$title, &$nt, &$wgUser, &$pageid, &$redirid ) {
|
| 112 | + $oldtitletext = $title->getText();
|
| 113 | + $oldns = $title->getNamespace();
|
| 114 | + $newtitletext = $nt->getText();
|
| 115 | + $newns = $nt->getNamespace();
|
| 116 | +
|
| 117 | + wfDebug( 'HIPP: ' . __METHOD__ . "\n" );
|
| 118 | +
|
| 119 | + if ($oldns != 0 && $newns != 0)
|
| 120 | + return true;
|
| 121 | +
|
| 122 | + # TODO we can't always check if we're moving a redirect because the old article's content
|
| 123 | + # TODO has already been replaced with the redirect to the new title but a
|
| 124 | + # TODO new title's content is still "noarticletext" at this point!
|
| 125 | + #$a1 = new Article( $title );
|
| 126 | + #$a2 = new Article( $nt );
|
| 127 | + #wfDebug( "HIPP: getContent() for isRedirect()\n\tfrom <<<" . $a1->getContent() . ">>>\n\t to <<<" . $a2->getContent() . ">>>\n" );
|
| 128 | + #if ($a1->isRedirect( $a->getContent() )) {
|
| 129 | + # wfDebug( "HIPP: moving a redirect (?)\n" );
|
| 130 | + # return true;
|
| 131 | + #}
|
| 132 | +
|
| 133 | + if ($oldns == 0 && $newns == 0) {
|
| 134 | + DidYouMean::doUpdate( $pageid, $newtitletext );
|
| 135 | + } elseif ($oldns == 0) {
|
| 136 | + DidYouMean::doDelete( $pageid );
|
| 137 | + } elseif ($newns == 0) {
|
| 138 | + DidYouMean::doInsert( $pageid, $newtitletext );
|
| 139 | + }
|
| 140 | +
|
| 141 | + return true;
|
| 142 | + }
|
| 143 | +
|
| 144 | + # called at action=edit. can detect if we're about to edit a redirect
|
| 145 | + public static function alternateEdit( $editpage ) {
|
| 146 | + global $wgParser;
|
| 147 | +
|
| 148 | + if ($editpage->mArticle->isRedirect())
|
| 149 | + $wgParser->mDymRedirBeforeEdit = true;
|
| 150 | +
|
| 151 | + return 1;
|
| 152 | + }
|
| 153 | +
|
| 154 | + # called at end of action=submit
|
| 155 | + public static function articleSaveComplete( $article, $user, $text, $summary, $isminor, $dunno1, $dunno2, $flags ) {
|
| 156 | + global $wgParser;
|
| 157 | +
|
| 158 | + if ($article->getTitle()->getNamespace() != 0)
|
| 159 | + return true;
|
| 160 | +
|
| 161 | + if ($article->isRedirect($text)) {
|
| 162 | + if (empty( $wgParser->mDymRedirBeforeEdit ) && !($flags & EDIT_NEW))
|
| 163 | + DidYouMean::doDelete( $article->getID() );
|
| 164 | + } else {
|
| 165 | + if (!empty( $wgParser->mDymRedirBeforeEdit ) || $flags & EDIT_NEW)
|
| 166 | + DidYouMean:doInsert( $article->getID(), $article->getTitle()->getText() );
|
| 167 | + }
|
| 168 | +
|
| 169 | + $wgParser->mDymRedirBeforeEdit = false;
|
| 170 | +
|
| 171 | + return true;
|
| 172 | + }
|
| 173 | +
|
| 174 | + public static function articleUndelete( &$title, &$create ) {
|
| 175 | +
|
| 176 | + if ($create == false || $title->getNamespace() != 0)
|
| 177 | + return true;
|
| 178 | +
|
| 179 | + # TODO it's not possible to detect if the undeleted article is a redirect!
|
| 180 | + #$artic1e = new Article( $title );
|
| 181 | + #if ($article->isRedirect( $article->getContent() )) {
|
| 182 | + # return true;
|
| 183 | + #}
|
| 184 | +
|
| 185 | + DidYouMean::doInsert( $title->getArticleId(), $title->getText() );
|
| 186 | +
|
| 187 | + return true;
|
| 188 | + }
|
| 189 | +
|
| 190 | + public static function parserTestTables( &$tables ) {
|
| 191 | + $tables[] = 'dympage';
|
| 192 | + $tables[] = 'dymnorm';
|
| 193 | + return true;
|
| 194 | + }
|
| 195 | +} |
\ No newline at end of file |