* Cleanup, may still contain some bugs due to it

This commit is contained in:
Niklas Laxström 2009-04-27 08:52:10 +00:00
parent e3948ccc50
commit 241d79f472
Notes: Yaron Koren 2009-07-20 18:49:29 +00:00
5 changed files with 303 additions and 260 deletions

2
README
View file

@ -1,6 +1,6 @@
Replace Text Extension
Version 0.4.1
Version 0.5.0
Yaron Koren
This is free software licenced under the GNU General Public Licence. Please

View file

@ -16,13 +16,13 @@ $messages['en'] = array(
'replacetext-desc' => 'Provides a [[Special:ReplaceText|special page]] to allow administrators to do a global string find-and-replace on all the content pages of a wiki',
'replacetext_docu' => 'To replace one text string with another across all regular pages on this wiki, enter the two pieces of text here and then hit \'Continue\'. You will then be shown a list of pages that contain the search text, and you can choose the ones in which you want to replace it. Your name will appear in page histories as the user responsible for any changes.',
'replacetext_note' => 'Note: this will not replace text in "Talk" pages and project pages.',
'replacetext_originaltext' => 'Original text',
'replacetext_replacementtext' => 'Replacement text',
'replacetext_originaltext' => 'Original text:',
'replacetext_replacementtext' => 'Replacement text:',
'replacetext_movepages' => 'Replace text in page titles as well, when possible',
'replacetext_choosepages' => 'Please select the {{PLURAL:$3|page|pages}} for which you want to replace \'$1\' with \'$2\':',
'replacetext_choosepagesformove' => 'Replace text in the {{PLURAL:$1|name of the following page|names of the following pages}}:',
'replacetext_cannotmove' => 'The following {{PLURAL:$1|page|pages}} cannot be moved:',
'replacetext_savemovedpages' => 'For moved pages, save the old titles as redirects to the new titles',
'replacetext_savemovedpages' => 'For moved pages, save the old titles as redirects to the new titles:',
'replacetext_invertselections' => 'Invert selections',
'replacetext_replace' => 'Replace',
'replacetext_success' => '\'$1\' will be replaced with \'$2\' in $3 {{PLURAL:$3|page|pages}}.',

12
ReplaceText.js Normal file
View file

@ -0,0 +1,12 @@
function invertSelections() {
form = document.getElementById('choose_pages');
num_elements = form.elements.length;
for (i = 0; i < num_elements; i++) {
if (form.elements[i].type == "checkbox") {
if (form.elements[i].checked == true)
form.elements[i].checked = false;
else
form.elements[i].checked = true;
}
}
}

View file

@ -25,8 +25,8 @@ if (!defined('MEDIAWIKI')) die();
$wgExtensionCredits['specialpage'][] = array(
'path' => __FILE__,
'name' => 'Replace Text',
'version' => '0.4.1',
'author' => 'Yaron Koren',
'version' => '0.5.0',
'author' => array( 'Yaron Koren', 'Niklas Laxström' ),
'url' => 'http://www.mediawiki.org/wiki/Extension:Replace_Text',
'description' => 'A special page that lets administrators run a global search-and-replace',
'descriptionmsg' => 'replacetext-desc',

View file

@ -20,289 +20,320 @@ class ReplaceText extends SpecialPage {
return;
}
$this->user = $wgUser;
$this->setHeaders();
doSpecialReplaceText();
$this->doSpecialReplaceText();
}
function displayConfirmForm($message) {
global $wgRequest, $wgContLang;
$target_str = $wgRequest->getVal('target_str');
$replacement_str = $wgRequest->getVal('replacement_str');
// HTML-escape strings before passing them in the form
$target_str = htmlentities($target_str);
$replacement_str = htmlentities($replacement_str);
$continue_label = wfMsg('replacetext_continue');
$cancel_label = wfMsg('replacetext_cancel');
// set 'title' as hidden field, in case there's no URL niceness
$mw_namespace_labels = $wgContLang->getNamespaces();
$special_namespace = $mw_namespace_labels[NS_SPECIAL];
$text =<<<END
<form method="post" action="">
<input type="hidden" name="title" value="$special_namespace:ReplaceText">
<input type="hidden" name="target_str" value="$target_str">
<input type="hidden" name="replacement_str" value="$replacement_str">
<p>$message</p>
<p><input type="Submit" name="confirm" value="$continue_label"></p>
<p>$cancel_label</p>
</form>
function displayConfirmForm( $message, $target, $replacement ) {
global $wgOut;
END;
return $text;
$formOpts = array( 'method' => 'post', 'action' => $this->getTitle()->getFullUrl() );
$wgOut->addHTML(
Xml::openElement( 'form', $formOpts ) .
Xml::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
Xml::hidden( 'target', $target ) .
Xml::hidden( 'replacement', $replacement ) .
Xml::hidden( 'confirm', 1 )
);
$wgOut->wrapWikiMsg( '$1', $message );
$wgOut->addHTML(
Xml::submitButton( wfMsg( 'replacetext_continue' ) )
);
$wgOut->addWikiMsg( 'replacetext_cancel' );
$wgOut->addHTML( Xml::closeElement( 'form' ) );
}
}
function doSpecialReplaceText() {
global $wgUser, $wgOut, $wgRequest, $wgContLang;
function doSpecialReplaceText() {
global $wgUser, $wgOut, $wgRequest, $wgLang;
// set 'title' as hidden field, in case there's no URL niceness
$mw_namespace_labels = $wgContLang->getNamespaces();
$special_namespace = $mw_namespace_labels[NS_SPECIAL];
$target = $wgRequest->getText('target');
$replacement = $wgRequest->getText('replacement');
if ($wgRequest->getCheck('replace')) {
$target_str = $wgRequest->getVal('target_str');
$replacement_str = $wgRequest->getVal('replacement_str');
$replacement_params = array();
$replacement_params['user_id'] = $wgUser->getId();
$replacement_params['target_str'] = $target_str;
$replacement_params['replacement_str'] = $replacement_str;
$replacement_params['edit_summary'] = wfMsgForContent('replacetext_editsummary', $target_str, $replacement_str);
$replacement_params['create_redirect'] = false;
foreach ($wgRequest->getValues() as $key => $value) {
if ($key == 'create-redirect' && $value == '1') {
$replacement_params['create_redirect'] = true;
}
if ( $target === '' ) {
if ( !$wgRequest->wasPosted() ) $this->showForm( 'replacetext_docu' );
else $this->showForm( 'replacetext_givetarget' );
return;
}
$jobs = array();
foreach ($wgRequest->getValues() as $key => $value) {
if ($value == '1') {
if (strpos($key, 'move-') !== false) {
$title = Title::newFromId(substr($key, 5));
$replacement_params['move_page'] = true;
} else {
$title = Title::newFromId($key);
if ($wgRequest->getCheck('replace')) {
$replacement_params = array();
$replacement_params['user_id'] = $wgUser->getId();
$replacement_params['target_str'] = $target;
$replacement_params['replacement_str'] = $replacement;
$replacement_params['edit_summary'] = wfMsgForContent('replacetext_editsummary', $target, $replacement );
$replacement_params['create_redirect'] = false;
foreach ($wgRequest->getValues() as $key => $value) {
if ($key == 'create-redirect' && $value == '1') {
$replacement_params['create_redirect'] = true;
}
if ($title !== null)
$jobs[] = new ReplaceTextJob( $title, $replacement_params );
}
}
Job::batchInsert( $jobs );
$num_modified_pages = count($jobs);
$wgOut->addHTML( wfMsgExt( 'replacetext_success', array( 'escape', 'parsemag' ), $target_str, $replacement_str, $num_modified_pages) );
// link back to starting form
$rt_title = Title::makeTitleSafe( NS_SPECIAL, 'ReplaceText' );
$sk = $wgUser->getSkin();
$wgOut->addHTML( '<p>' . $sk->makeKnownLinkObj( $rt_title, wfMsg( 'replacetext_return' ) ) . '</p>' );
} elseif ( $wgRequest->getCheck('target_str') ) { // very long elseif, look for "end elseif"
$dbr =& wfGetDB( DB_SLAVE );
$fname = 'doSpecialReplaceText';
$target_str = $wgRequest->getVal('target_str');
$replacement_str = $wgRequest->getVal('replacement_str');
$jobs = array();
foreach ($wgRequest->getValues() as $key => $value) {
if ($value == '1') {
if (strpos($key, 'move-') !== false) {
$title = Title::newFromId(substr($key, 5));
$replacement_params['move_page'] = true;
} else {
$title = Title::newFromId($key);
}
if ($title !== null)
$jobs[] = new ReplaceTextJob( $title, $replacement_params );
}
}
Job::batchInsert( $jobs );
$count = $wgLang->formatNum( count($jobs) );
$wgOut->addWikiMsg( 'replacetext_success', $target, $replacement, $count );
// Link back
$wgOut->addHTML( $sk->link( $this->getTitle(), wfMsgHtml( 'replacetext_return' ) ) );
} elseif ( $wgRequest->getCheck('target') ) { // very long elseif, look for "end elseif"
if (! $wgRequest->getCheck('confirm')) {
// display a page to make the user confirm the replacement, if the
// replacement string is either blank or found elsewhere on the wiki
// (since undoing the replacement would be difficult in either case)
if ($replacement_str == '') {
$text = wfMsg('replacetext_blankwarning');
$wgOut->addHTML(ReplaceText::displayConfirmForm($text));
return;
} else {
// get the number of pages in which the replacement string appears
$page_table = $dbr->tableName('page');
$revision_table = $dbr->tableName('revision');
$text_table = $dbr->tableName('text');
$talk_ns = NS_TALK;
$usertalk_ns = NS_USER_TALK;
$mediawiki_ns = NS_MEDIAWIKI;
$sql_replacement_str = str_replace("'", "\'", $replacement_str);
$sql = "SELECT count(*)
FROM $page_table p
JOIN $revision_table r ON p.page_latest = r.rev_id
JOIN $text_table t ON r.rev_text_id = t.old_id
WHERE t.old_text LIKE '%$sql_replacement_str%'
AND p.page_namespace != $talk_ns
AND p.page_namespace != $usertalk_ns
AND p.page_namespace != $mediawiki_ns";
$res = $dbr->query($sql);
$row = $dbr->fetchRow($res);
$num_pages_with_replacement_str = $row[0];
// if there are any, the user most confirm the replacement
if ($num_pages_with_replacement_str > 0) {
$text = wfMsgExt( 'replacetext_warning', array( 'escape', 'parsemag' ), $num_pages_with_replacement_str, $replacement_str );
$wgOut->addHTML(ReplaceText::displayConfirmForm($text));
if (!$wgRequest->getCheck('confirm')) {
$message = false;
if ($replacement === '') {
$message = 'replacetext_blankwarning';
} else {
$res = $this->doSearchQuery( $replacement );
$count = $res->numRows();
if ( $count ) {
$message = array( 'replacetext_warning', $wgLang->formatNum( $count ), $replacement );
}
}
if ( $message ) {
$this->displayConfirmForm( $message, $target, $replacement );
return;
}
}
}
$jobs = array();
$num_modified_pages = 0;
$found_titles = array();
$titles_for_move = array();
$unmoveable_titles = array();
$angle_brackets = array('<', '>');
$escaped_angle_brackets = array('&lt;', '&gt;');
// get the set of pages that contain the target string, and display
// the name and "context" (the text around the string) of each
$page_table = $dbr->tableName('page');
$revision_table = $dbr->tableName('revision');
$text_table = $dbr->tableName('text');
$talk_ns = NS_TALK;
$usertalk_ns = NS_USER_TALK;
$mediawiki_ns = NS_MEDIAWIKI;
// escape single quote and backslash for SQL - for some reason, the
// backslash needs to be escaped twice (plus once for PHP)
$sql_target_str = str_replace(array("\\", "'"), array("\\\\\\\\", "\'"), $target_str);
# FIXME: suggestions for improvement at http://www.mediawiki.org/wiki/Special:Code/MediaWiki/43239#c608
$sql = "SELECT p.page_title AS title, p.page_namespace AS namespace, t.old_text AS text
FROM $page_table p
JOIN $revision_table r ON p.page_latest = r.rev_id
JOIN $text_table t ON r.rev_text_id = t.old_id
WHERE t.old_text LIKE '%$sql_target_str%'
AND p.page_namespace != $talk_ns
AND p.page_namespace != $usertalk_ns
AND p.page_namespace != $mediawiki_ns
ORDER BY p.page_namespace, p.page_title";
$res = $dbr->query($sql);
$contextchars = $wgUser->getOption( 'contextchars', 40 );
while( $row = $dbr->fetchObject( $res ) ) {
$title = Title::makeTitleSafe($row->namespace, $row->title);
$article_text = $row->text;
$target_pos = strpos($article_text, $target_str);
$context_str = str_replace($angle_brackets, $escaped_angle_brackets, $wgContLang->truncate(substr($article_text, 0, $target_pos), -$contextchars ) );
$context_str .= "<span class=\"searchmatch\">" . str_replace($angle_brackets, $escaped_angle_brackets, substr($article_text, $target_pos, strlen($target_str))) . "</span>";
$context_str .= str_replace($angle_brackets, $escaped_angle_brackets, $wgContLang->truncate(substr($article_text, $target_pos + strlen($target_str)), $contextchars ) );
$found_titles[] = array($title, $context_str);
$num_modified_pages++;
}
if ($wgRequest->getCheck('move_pages')) {
$sql_target_str2 = str_replace(' ', '_', $sql_target_str);
$sql2 = "SELECT p.page_title AS title, p.page_namespace AS namespace
FROM $page_table p
WHERE p.page_title LIKE '%$sql_target_str2%'
ORDER BY p.page_namespace, p.page_title";
$res = $dbr->query($sql2);
while( $row = $dbr->fetchObject( $res ) ) {
$title = Title::makeTitleSafe($row->namespace, $row->title);
// see if this move can happen
$cur_page_name = str_replace('_', ' ', $row->title);
$new_page_name = str_replace($target_str, $replacement_str, $cur_page_name);
$new_title = Title::makeTitleSafe($row->namespace, $new_page_name);
$err = $title->isValidMoveOperation($new_title);
if ($title->userCanMove(true) && (! is_array($err))) {
$titles_for_move[] = $title;
$num_modified_pages++;
} else {
$unmoveable_titles[] = $title;
$jobs = array();
$found_titles = array();
$titles_for_move = array();
$unmoveable_titles = array();
$res = $this->doSearchQuery( $target );
foreach ( $res as $row ) {
$title = Title::makeTitleSafe($row->page_namespace, $row->page_title);
$context = $this->extractContext( $row->old_text, $target );
$found_titles[] = array( $title, $context );
}
if ( $wgRequest->getCheck('move_pages') ) {
$res = $this->getMoveTitles( $target );
foreach ( $res as $row ) {
$title = Title::makeTitleSafe($row->page_namespace, $row->page_title);
// see if this move can happen
$new_title = Title::makeTitleSafe( $row->page_namespace, str_replace( $target, $replacement, $row->page_title ) );
$err = $title->isValidMoveOperation($new_title);
if ( $title->userCanMove(true) && !is_array($err) ) {
$titles_for_move[] = $title;
} else {
$unmoveable_titles[] = $title;
}
}
}
}
if ($num_modified_pages == 0) {
$wgOut->addHTML(wfMsg('replacetext_noreplacement', $target_str));
// link back to starting form
$rt_title = Title::makeTitleSafe( NS_SPECIAL, 'ReplaceText' );
$sk = $wgUser->getSkin();
$wgOut->addHTML( '<p>' . $sk->makeKnownLinkObj( $rt_title, wfMsg( 'replacetext_return' ) ) . '</p>' );
} else {
$javascript_text =<<<END
<script type="text/javascript">
function invertSelections() {
form = document.getElementById('choose_pages');
num_elements = form.elements.length;
for (i = 0; i < num_elements; i++) {
if (form.elements[i].type == "checkbox") {
if (form.elements[i].checked == true)
form.elements[i].checked = false;
else
form.elements[i].checked = true;
if ( !$res->numRows() ) {
$wgOut->addWikiMsg( 'replacetext_noreplacement', $target );
// link back to starting form
$sk = $this->user->getSkin();
$wgOut->addHTML( '<p>' . $sk->makeKnownLinkObj( $this->getTitle(), wfMsg( 'replacetext_return' ) ) . '</p>' );
} else {
$this->pageListForm( $target, $replacement, $found_titles, $titles_for_move, $unmoveable_titles );
}
}
}
}
</script>
END;
$wgOut->addScript($javascript_text);
$replace_label = wfMsg('replacetext_replace');
$choose_pages_label = wfMsgExt('replacetext_choosepages', array( 'escape', 'parsemag' ), $target_str, $replacement_str, count( $found_titles ) );
$choose_pages_for_move_label = wfMsgExt( 'replacetext_choosepagesformove', array( 'escape', 'parsemag' ), count( $titles_for_move ) );
$cannot_move_pages_label = wfMsgExt( 'replacetext_cannotmove', array( 'escape', 'parsemag' ), count( $unmoveable_titles ) );
$skin = $wgUser->getSkin();
// HTML-escape strings before passing them in the form
$target_str = htmlentities($target_str);
$replacement_str = htmlentities($replacement_str);
$text =<<<END
<p>$choose_pages_label</p>
<form id="choose_pages" method="post">
<input type="hidden" name="title" value="$special_namespace:ReplaceText">
<input type="hidden" name="target_str" value="$target_str">
<input type="hidden" name="replacement_str" value="$replacement_str">
function showForm( $message ) {
global $wgOut;
$wgOut->addHTML(
Xml::openElement( 'form', array( 'action' => $this->getTitle()->getFullUrl(), 'method' => 'post' ) ) .
Xml::hidden( 'title', $this->getTitle()->getPrefixedText() )
);
$wgOut->addWikiMsg( $message );
$wgOut->addWikiMsg( 'replacetext_note' );
$wgOut->wrapWikiMsg( '<table><tr><td>$1</td><td>', 'replacetext_originaltext' );
$wgOut->addHTML( Xml::input( 'target', 10 ) );
$wgOut->wrapWikiMsg( '</td></tr><tr><td>$1</td><td>', 'replacetext_replacementtext' );
$wgOut->addHTML( Xml::input( 'replacement', 10 ) );
$wgOut->addHTML( '</td></tr></table>' );
$wgOut->addHTML(
Xml::checkLabel( wfMsg( 'replacetext_movepages' ), 'move_pages', 'move_pages' ) . '<br />' .
Xml::submitButton( wfMsg( 'replacetext_continue' ) ) .
Xml::closeElement( 'form' )
);
}
END;
foreach ($found_titles as $value_pair) {
list($title, $context_str) = $value_pair;
$text .= Xml::check($title->getArticleID(), true);
$text .= " " . $skin->makeLinkObj( $title, $title->prefix($title->getText()) ) . " - <small>$context_str</small><br />\n";
}
if (count($titles_for_move) > 0) {
$text .= "<br />\n<p>$choose_pages_for_move_label</p>\n";
foreach ($titles_for_move as $title) {
$text .= Xml::check('move-' . $title->getArticleID(), true);
$text .= " " . $skin->makeLinkObj( $title, $title->prefix($title->getText()) ) . "<br />\n";
}
$text .= '<p>' . wfMsg('replacetext_savemovedpages') . wfMsg('colon-separator');
$text .= Xml::check('create-redirect', true) . "</p>\n";
function pageListForm( $target, $replacement, $found_titles, $titles_for_move, $unmoveable_titles ) {
global $wgOut, $wgLang, $wgScript;
$js = file_get_contents( dirname( __FILE__ ) . '/ReplaceText.js' );
$js = '<script type="text/javascript">' . $js . '</script>';
$wgOut->addScript($js);
$wgOut->addWikiMsg( 'replacetext_choosepages', $target, $replacement,
$wgLang->formatNum( count( $found_titles ) ) );
$formOpts = array( 'id' => 'choose_pages', 'method' => 'post', 'action' => $this->getTitle()->getFullUrl() );
$wgOut->addHTML(
Xml::openElement( 'form', $formOpts ) .
Xml::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
Xml::hidden( 'target', $target ) .
Xml::hidden( 'replace', $replacement )
);
$skin = $this->user->getSkin();
foreach ( $found_titles as $_ ) {
list( $title, $context ) = $_;
$wgOut->addHTML(
Xml::check( $title->getArticleID(), true) .
$skin->makeKnownLinkObj( $title, $title->getPrefixedText() ) . " - <small>$context</small><br />\n"
);
}
$text .=<<<END
<p><input type="Submit" name="replace" value="$replace_label"></p>
END;
if ( count($titles_for_move) ) {
$wgOut->addHTML( '<br />' );
$wgOut->addWikiMsg( 'replacetext_choosepagesformove', $wgLang->formatNum( count( $titles_for_move ) ) );
foreach ($titles_for_move as $title) {
$wgOut->addHTML(
Xml::check('move-' . $title->getArticleID(), true) .
$skin->makeLinkObj( $title, $title->prefix($title->getText()) ) . "<br />\n"
);
}
$wgOut->addHTML(
Xml::checkLabel( wfMsg( 'replacetext_savemovedpages' ), 'create-redirect', 'create-redirect', true )
);
}
$wgOut->addHTML(
'<br />' .
Xml::submitButton( wfMsg('replacetext_replace') ) .
Xml::hidden( 'replace', 1 )
);
// only show "invert selections" link if there are more than five pages
if (count($found_titles) + count($titles_for_move) > 5) {
$invert_selections_label = wfMsg('replacetext_invertselections');
$text .=<<<END
<p><a href="javascript:;" onclick="invertSelections(); return false;">$invert_selections_label</a></p>
$buttonOpts = array(
'type' => 'button',
'value' => wfMsg( 'replacetext_invertselections' ),
'onclick' => 'invertSelections(); return false;'
);
END;
}
$text .= " </form>\n";
if (count($unmoveable_titles) > 0) {
$text .= "<p>$cannot_move_pages_label</p>\n";
$text .= "<ul>\n";
foreach ($unmoveable_titles as $title) {
$text .= "<li>{$skin->makeLinkObj( $title, $title->prefix($title->getText()) )}<br />\n";
}
$text .= "</ul>\n";
$wgOut->addHTML(
Xml::element( 'input', $buttonOpts )
);
}
$wgOut->addHTML($text);
}
} // end elseif
else {
$replacement_label = wfMsg('replacetext_docu');
$replacement_note = wfMsg('replacetext_note');
$original_text_label = wfMsg('replacetext_originaltext');
$replacement_text_label = wfMsg('replacetext_replacementtext');
$move_pages_label = wfMsg('replacetext_movepages');
$continue_label = wfMsg('replacetext_continue');
$text =<<<END
<form method="get" action="">
<input type="hidden" name="title" value="$special_namespace:ReplaceText">
<p>$replacement_label</p>
<p>$replacement_note</p>
<table>
<tr>
<td>$original_text_label:</td>
<td><input type="text" length="10" name="target_str"></td>
</tr>
<tr>
<td>$replacement_text_label:</td>
<td><input type="text" length="10" name="replacement_str"></td>
</tr>
</table>
<p><input type="checkbox" name="move_pages"> $move_pages_label</p>
<p><input type="Submit" value="$continue_label"></p>
</form>
END;
$wgOut->addHTML($text);
$wgOut->addHTML( '</form>' );
if (count($unmoveable_titles) > 0) {
$wgOut->addWikiMsg( 'replacetext_cannotmove', $wgLang->formatNum( count( $unmoveable_titles ) ) );
$text = "<ul>\n";
foreach ($unmoveable_titles as $title) {
$text .= "<li>{$skin->makeKnownLinkObj( $title, $title->getPrefixedText() )}<br />\n";
}
$text .= "</ul>\n";
$wgOut->addHTML($text);
}
}
/**
* Extract context and highlights search text
*/
function extractContext( $text, $target ) {
global $wgLang;
$cw = $this->user->getOption( 'contextchars', 40 );
// Get all indexes
$targetq = preg_quote( $target, '/' );
preg_match_all( "/$targetq/i", $text, $matches, PREG_OFFSET_CAPTURE );
$poss = array();
foreach ( $matches[0] as $_ ) {
$poss[] = $_[1];
}
$cuts = array();
for ( $i = 0; $i < count($poss); $i++ ) {
$index = $poss[$i];
$len = strlen($target);
// Merge to the next if possible
while( isset($poss[$i+1]) ) {
if ( $poss[$i+1] < $index+$len+$cw*2 ) {
$len += $poss[$i+1] - $poss[$i];
$i++;
} else {
break; // Can't merge, exit the inner loop
}
}
$cuts[] = array( $index, $len );
}
$context = '';
foreach ($cuts as $_ ) {
list( $index, $len, ) = $_;
$context .= self::convertWhiteSpaceToHTML( $wgLang->truncate( substr( $text, 0, $index ), -$cw ) );
$snippet = self::convertWhiteSpaceToHTML( substr( $text, $index, $len ) );
$targetq = preg_quote( self::convertWhiteSpaceToHTML( $target ), '/' );
$context .= preg_replace( "/$targetq/i", '<span class="searchmatch">\0</span>', $snippet );
$context .= self::convertWhiteSpaceToHTML( $wgLang->truncate( substr( $text, $index+$len ), $cw ) );
}
return $context;
}
public static function convertWhiteSpaceToHTML( $msg ) {
$msg = htmlspecialchars( $msg );
$msg = preg_replace( '/^ /m', '&nbsp; ', $msg );
$msg = preg_replace( '/ $/m', ' &nbsp;', $msg );
$msg = preg_replace( '/ /', '&nbsp; ', $msg );
#$msg = str_replace( "\n", '<br />', $msg );
return $msg;
}
function getMoveTitles( $target ) {
$title = Title::newFromText( $target );
if ( !$title ) return array();
$dbr = wfGetDB( DB_SLAVE );
$target = $dbr->escapeLike( $title->getDbKey() );
return $dbr->select(
'page',
array( 'page_title', 'page_namespace' ),
"page_title like '%$target%'",
__METHOD__,
array( 'ORDER BY' => 'page_namespace, page_title')
);
}
function doSearchQuery( $search ) {
$dbr = wfGetDB( DB_SLAVE );
$search = $dbr->escapeLike( $search );
$exemptNS = $dbr->makeList( array( NS_TALK, NS_USER_TALK ) );
$tables = array( 'page', 'revision', 'text' );
$vars = array( 'page_id', 'page_namespace', 'page_title', 'old_text' );
$conds = array(
"old_text like '%$search%'",
"page_namespace not in ($exemptNS)",
'rev_id = page_latest',
'rev_text_id = old_id'
);
return $dbr->select( $tables, $vars, $conds, __METHOD__ );
}
}