70 parent::__construct(
'MergeHistory',
'mergehistory' );
82 $this->mAction = $request->getVal(
'action' );
83 $this->mTarget = $request->getVal(
'target' );
84 $this->mDest = $request->getVal(
'dest' );
85 $this->mSubmitted = $request->getBool(
'submitted' );
87 $this->mTargetID = intval( $request->getVal(
'targetID' ) );
88 $this->mDestID = intval( $request->getVal(
'destID' ) );
89 $this->mTimestamp = $request->getVal(
'mergepoint' );
90 if ( !preg_match(
'/[0-9]{14}/', $this->mTimestamp ) ) {
91 $this->mTimestamp =
'';
93 $this->mComment = $request->getText(
'wpComment' );
95 $this->mMerge = $request->wasPosted()
96 && $this->
getUser()->matchEditToken( $request->getVal(
'wpEditToken' ) );
99 if ( $this->mSubmitted ) {
100 $this->mTargetObj = Title::newFromText( $this->mTarget );
101 $this->mDestObj = Title::newFromText( $this->mDest );
103 $this->mTargetObj =
null;
104 $this->mDestObj =
null;
119 if ( $this->mTargetID && $this->mDestID && $this->mAction ==
'submit' && $this->mMerge ) {
125 if ( !$this->mSubmitted ) {
132 if ( !$this->mTargetObj instanceof
Title ) {
133 $errors[] = $this->
msg(
'mergehistory-invalid-source' )->parseAsBlock();
134 } elseif ( !$this->mTargetObj->exists() ) {
135 $errors[] = $this->
msg(
'mergehistory-no-source',
140 if ( !$this->mDestObj instanceof
Title ) {
141 $errors[] = $this->
msg(
'mergehistory-invalid-destination' )->parseAsBlock();
142 } elseif ( !$this->mDestObj->exists() ) {
143 $errors[] = $this->
msg(
'mergehistory-no-destination',
148 if ( $this->mTargetObj && $this->mDestObj && $this->mTargetObj->equals( $this->mDestObj ) ) {
149 $errors[] = $this->
msg(
'mergehistory-same-destination' )->parseAsBlock();
152 if ( count( $errors ) ) {
154 $this->
getOutput()->addHTML( implode(
"\n", $errors ) );
162 $out->addWikiMsg(
'mergehistory-header' );
165 Xml::openElement(
'form', [
169 Xml::element(
'legend', [],
170 $this->
msg(
'mergehistory-box' )->text() ) .
171 Html::hidden(
'title', $this->
getPageTitle()->getPrefixedDBkey() ) .
172 Html::hidden(
'submitted',
'1' ) .
173 Html::hidden(
'mergepoint', $this->mTimestamp ) .
174 Xml::openElement(
'table' ) .
176 <td>' . Xml::label( $this->
msg(
'mergehistory-from' )->text(),
'target' ) .
'</td>
177 <td>' . Xml::input(
'target', 30, $this->mTarget, [
'id' =>
'target' ] ) .
'</td>
179 <td>' . Xml::label( $this->
msg(
'mergehistory-into' )->text(),
'dest' ) .
'</td>
180 <td>' . Xml::input(
'dest', 30, $this->mDest, [
'id' =>
'dest' ] ) .
'</td>
182 Xml::submitButton( $this->
msg(
'mergehistory-go' )->text() ) .
184 Xml::closeElement(
'table' ) .
195 # List all stored revisions
197 $this, [], $this->mTargetObj, $this->mDestObj
199 $haveRevisions = $revisions && $revisions->getNumRows() > 0;
203 $action = $titleObj->getLocalURL( [
'action' =>
'submit' ] );
204 # Start the form here
205 $top = Xml::openElement(
213 $out->addHTML( $top );
215 if ( $haveRevisions ) {
216 # Format the user-visible controls (comment field, submission button)
217 # in a nice little table
219 Xml::openElement(
'fieldset' ) .
220 $this->
msg(
'mergehistory-merge', $this->mTargetObj->getPrefixedText(),
221 $this->mDestObj->getPrefixedText() )->parse() .
222 Xml::openElement(
'table', [
'id' =>
'mw-mergehistory-table' ] ) .
224 <td class="mw-label">' .
225 Xml::label( $this->
msg(
'mergehistory-reason' )->text(),
'wpComment' ) .
227 <td class="mw-input">' .
228 Xml::input(
'wpComment', 50, $this->mComment, [
'id' =>
'wpComment' ] ) .
233 <td class=\"mw-submit\">" .
235 $this->
msg(
'mergehistory-submit' )->text(),
236 [
'name' =>
'merge',
'id' =>
'mw-merge-submit' ]
240 Xml::closeElement(
'table' ) .
241 Xml::closeElement(
'fieldset' );
243 $out->addHTML( $table );
247 '<h2 id="mw-mergehistory">' .
248 $this->
msg(
'mergehistory-list' )->escaped() .
"</h2>\n"
251 if ( $haveRevisions ) {
252 $out->addHTML( $revisions->getNavigationBar() );
253 $out->addHTML(
'<ul>' );
254 $out->addHTML( $revisions->getBody() );
255 $out->addHTML(
'</ul>' );
256 $out->addHTML( $revisions->getNavigationBar() );
258 $out->addWikiMsg(
'mergehistory-empty' );
261 # Show relevant lines from the merge log:
262 $mergeLogPage =
new LogPage(
'merge' );
263 $out->addHTML(
'<h2>' . $mergeLogPage->getName()->escaped() .
"</h2>\n" );
266 # When we submit, go by page ID to avoid some nasty but unlikely collisions.
267 # Such would happen if a page was renamed after the form loaded, but before submit
268 $misc = Html::hidden(
'targetID', $this->mTargetObj->getArticleID() );
269 $misc .= Html::hidden(
'destID', $this->mDestObj->getArticleID() );
270 $misc .= Html::hidden(
'target', $this->mTarget );
271 $misc .= Html::hidden(
'dest', $this->mDest );
272 $misc .= Html::hidden(
'wpEditToken', $this->
getUser()->getEditToken() );
273 $misc .= Xml::closeElement(
'form' );
274 $out->addHTML( $misc );
285 $last = $this->
msg(
'last' )->escaped();
288 $checkBox = Xml::radio(
'mergepoint', $ts, ( $this->mTimestamp === $ts ) );
294 $this->getLanguage()->userTimeAndDate( $ts, $user ),
296 [
'oldid' => $rev->getId() ]
298 if ( $rev->isDeleted( RevisionRecord::DELETED_TEXT ) ) {
299 $pageLink =
'<span class="history-deleted">' . $pageLink .
'</span>';
303 if ( !$rev->userCan( RevisionRecord::DELETED_TEXT, $user ) ) {
304 $last = $this->
msg(
'last' )->escaped();
305 } elseif ( isset( $this->prevId[$row->rev_id] ) ) {
308 $this->msg(
'last' )->text(),
311 'diff' => $row->rev_id,
312 'oldid' => $this->prevId[$row->rev_id]
319 $size = $row->rev_len;
320 if ( !is_null( $size ) ) {
325 return Html::rawElement(
'li', [],
326 $this->
msg(
'mergehistory-revisionrow' )
327 ->rawParams( $checkBox,
$last, $pageLink, $userLink, $stxt, $comment )->escaped() );
343 # Get the titles directly from the IDs, in case the target page params
344 # were spoofed. The queries are done based on the IDs, so it's best to
345 # keep it consistent...
346 $targetTitle = Title::newFromID( $this->mTargetID );
347 $destTitle = Title::newFromID( $this->mDestID );
348 if ( is_null( $targetTitle ) || is_null( $destTitle ) ) {
351 if ( $targetTitle->getArticleID() == $destTitle->getArticleID() ) {
356 $mh =
new MergeHistory( $targetTitle, $destTitle, $this->mTimestamp );
359 $mergeStatus = $mh->merge( $this->
getUser(), $this->mComment );
360 if ( !$mergeStatus->isOK() ) {
362 $this->
getOutput()->addWikiMsg( $mergeStatus->getMessage() );
372 [
'redirect' =>
'no' ]
375 $this->
getOutput()->addWikiMsg( $this->
msg(
'mergehistory-done' )
376 ->rawParams( $targetLink )
377 ->params( $destTitle->getPrefixedText() )
378 ->numParams( $mh->getMergedRevisionCount() )
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
static revComment(Revision $rev, $local=false, $isPublic=false, $useParentheses=true)
Wrap and format the given revision's comment block, if the current user is allowed to view it.
static formatRevisionSize( $size)
static revUserTools( $rev, $isPublic=false, $useParentheses=true)
Generate a user tool link cluster if the current user is allowed to view it.
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
Class to simplify the use of log pages.
Handles the backend logic of merging the histories of two pages.
Special page allowing users with the appropriate permissions to merge article histories,...
merge()
Actually attempt the history move.
doesWrites()
Indicates whether this special page may perform database writes.
bool $mSubmitted
Was submitted?
execute( $par)
Default execute method Checks user permissions.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Parent class for all special pages.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getOutput()
Get the OutputPage being used for this instance.
getUser()
Shortcut to get the User executing this instance.
checkPermissions()
Checks if userCanExecute, and if not throws a PermissionsError.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getRequest()
Get the WebRequest being used for this instance.
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
getPageTitle( $subpage=false)
Get a self-referential title object.
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
MediaWiki Linker LinkRenderer null $linkRenderer
Represents a title within MediaWiki.