isAllowed('replacetext') ) { $wgOut->permissionRequired('replacetext'); return; } $this->setHeaders(); 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 =<<

$message

$cancel_label

END; return $text; } } function doSpecialReplaceText() { global $wgUser, $wgOut, $wgRequest, $wgContLang; // set 'title' as hidden field, in case there's no URL niceness $mw_namespace_labels = $wgContLang->getNamespaces(); $special_namespace = $mw_namespace_labels[NS_SPECIAL]; 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; } } $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 ); $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( '

' . $sk->makeKnownLinkObj( $rt_title, wfMsg( 'replacetext_return' ) ) . '

' ); } 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'); 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)); return; } } } $jobs = array(); $num_modified_pages = 0; $found_titles = array(); $titles_for_move = array(); $unmoveable_titles = array(); $angle_brackets = array('<', '>'); $escaped_angle_brackets = array('<', '>'); // 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 .= "" . str_replace($angle_brackets, $escaped_angle_brackets, substr($article_text, $target_pos, strlen($target_str))) . ""; $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; } } } 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( '

' . $sk->makeKnownLinkObj( $rt_title, wfMsg( 'replacetext_return' ) ) . '

' ); } else { $javascript_text =<< 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; } } } 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 =<<$choose_pages_label

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()) ) . " - $context_str
\n"; } if (count($titles_for_move) > 0) { $text .= "
\n

$choose_pages_for_move_label

\n"; foreach ($titles_for_move as $title) { $text .= Xml::check('move-' . $title->getArticleID(), true); $text .= " " . $skin->makeLinkObj( $title, $title->prefix($title->getText()) ) . "
\n"; } $text .= '

' . wfMsg('replacetext_savemovedpages') . wfMsg('colon-separator'); $text .= Xml::check('create-redirect', true) . "

\n"; } $text .=<<

END; // 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 .=<<$invert_selections_label

END; } $text .= " \n"; if (count($unmoveable_titles) > 0) { $text .= "

$cannot_move_pages_label

\n"; $text .= "
    \n"; foreach ($unmoveable_titles as $title) { $text .= "
  • {$skin->makeLinkObj( $title, $title->prefix($title->getText()) )}
    \n"; } $text .= "
\n"; } $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 =<<

$replacement_label

$replacement_note

$original_text_label:
$replacement_text_label:

$move_pages_label

END; $wgOut->addHTML($text); } }