71 parent::__construct(
'MergeHistory',
'mergehistory' );
83 $this->mAction = $request->getVal(
'action' );
84 $this->mTarget = $request->getVal(
'target',
'' );
85 $this->mDest = $request->getVal(
'dest',
'' );
86 $this->mSubmitted = $request->getBool(
'submitted' );
88 $this->mTargetID = intval( $request->getVal(
'targetID' ) );
89 $this->mDestID = intval( $request->getVal(
'destID' ) );
90 $this->mTimestamp = $request->getVal(
'mergepoint' );
91 if ( $this->mTimestamp ===
null || !preg_match(
'/[0-9]{14}/', $this->mTimestamp ) ) {
92 $this->mTimestamp =
'';
94 $this->mComment = $request->getText(
'wpComment' );
96 $this->mMerge = $request->wasPosted()
97 && $this->
getUser()->matchEditToken( $request->getVal(
'wpEditToken' ) );
100 if ( $this->mSubmitted ) {
101 $this->mTargetObj = Title::newFromText( $this->mTarget );
102 $this->mDestObj = Title::newFromText( $this->mDest );
104 $this->mTargetObj =
null;
105 $this->mDestObj =
null;
120 if ( $this->mTargetID && $this->mDestID && $this->mAction ==
'submit' && $this->mMerge ) {
126 if ( !$this->mSubmitted ) {
133 if ( !$this->mTargetObj instanceof
Title ) {
134 $errors[] = $this->
msg(
'mergehistory-invalid-source' )->parseAsBlock();
135 } elseif ( !$this->mTargetObj->exists() ) {
136 $errors[] = $this->
msg(
'mergehistory-no-source',
141 if ( !$this->mDestObj instanceof
Title ) {
142 $errors[] = $this->
msg(
'mergehistory-invalid-destination' )->parseAsBlock();
143 } elseif ( !$this->mDestObj->exists() ) {
144 $errors[] = $this->
msg(
'mergehistory-no-destination',
149 if ( $this->mTargetObj && $this->mDestObj && $this->mTargetObj->equals( $this->mDestObj ) ) {
150 $errors[] = $this->
msg(
'mergehistory-same-destination' )->parseAsBlock();
153 if ( count( $errors ) ) {
155 $this->
getOutput()->addHTML( implode(
"\n", $errors ) );
163 $out->addWikiMsg(
'mergehistory-header' );
166 Xml::openElement(
'form', [
170 Xml::element(
'legend', [],
171 $this->
msg(
'mergehistory-box' )->text() ) .
172 Html::hidden(
'title', $this->
getPageTitle()->getPrefixedDBkey() ) .
173 Html::hidden(
'submitted',
'1' ) .
174 Html::hidden(
'mergepoint', $this->mTimestamp ) .
175 Xml::openElement(
'table' ) .
177 <td>' . Xml::label( $this->
msg(
'mergehistory-from' )->text(),
'target' ) .
'</td>
178 <td>' . Xml::input(
'target', 30, $this->mTarget, [
'id' =>
'target' ] ) .
'</td>
180 <td>' . Xml::label( $this->
msg(
'mergehistory-into' )->text(),
'dest' ) .
'</td>
181 <td>' . Xml::input(
'dest', 30, $this->mDest, [
'id' =>
'dest' ] ) .
'</td>
183 Xml::submitButton( $this->
msg(
'mergehistory-go' )->text() ) .
185 Xml::closeElement(
'table' ) .
196 # List all stored revisions
198 $this, [], $this->mTargetObj, $this->mDestObj
200 $haveRevisions = $revisions->getNumRows() > 0;
204 $action = $titleObj->getLocalURL( [
'action' =>
'submit' ] );
205 # Start the form here
206 $top = Xml::openElement(
214 $out->addHTML( $top );
216 if ( $haveRevisions ) {
217 # Format the user-visible controls (comment field, submission button)
218 # in a nice little table
220 Xml::openElement(
'fieldset' ) .
221 $this->
msg(
'mergehistory-merge', $this->mTargetObj->getPrefixedText(),
222 $this->mDestObj->getPrefixedText() )->parse() .
223 Xml::openElement(
'table', [
'id' =>
'mw-mergehistory-table' ] ) .
225 <td class="mw-label">' .
226 Xml::label( $this->
msg(
'mergehistory-reason' )->text(),
'wpComment' ) .
228 <td class="mw-input">' .
229 Xml::input(
'wpComment', 50, $this->mComment, [
'id' =>
'wpComment' ] ) .
234 <td class=\"mw-submit\">" .
236 $this->
msg(
'mergehistory-submit' )->text(),
237 [
'name' =>
'merge',
'id' =>
'mw-merge-submit' ]
241 Xml::closeElement(
'table' ) .
242 Xml::closeElement(
'fieldset' );
244 $out->addHTML( $table );
248 '<h2 id="mw-mergehistory">' .
249 $this->
msg(
'mergehistory-list' )->escaped() .
"</h2>\n"
252 if ( $haveRevisions ) {
253 $out->addHTML( $revisions->getNavigationBar() );
254 $out->addHTML(
'<ul>' );
255 $out->addHTML( $revisions->getBody() );
256 $out->addHTML(
'</ul>' );
257 $out->addHTML( $revisions->getNavigationBar() );
259 $out->addWikiMsg(
'mergehistory-empty' );
262 # Show relevant lines from the merge log:
263 $mergeLogPage =
new LogPage(
'merge' );
264 $out->addHTML(
'<h2>' . $mergeLogPage->getName()->escaped() .
"</h2>\n" );
265 LogEventsList::showLogExtract( $out,
'merge', $this->mTargetObj );
267 # When we submit, go by page ID to avoid some nasty but unlikely collisions.
268 # Such would happen if a page was renamed after the form loaded, but before submit
269 $misc = Html::hidden(
'targetID', $this->mTargetObj->getArticleID() );
270 $misc .= Html::hidden(
'destID', $this->mDestObj->getArticleID() );
271 $misc .= Html::hidden(
'target', $this->mTarget );
272 $misc .= Html::hidden(
'dest', $this->mDest );
273 $misc .= Html::hidden(
'wpEditToken', $this->
getUser()->getEditToken() );
274 $misc .= Xml::closeElement(
'form' );
275 $out->addHTML( $misc );
281 $revRecord = MediaWikiServices::getInstance()
282 ->getRevisionFactory()
283 ->newRevisionFromRow( $row );
288 $last = $this->
msg(
'last' )->escaped();
291 $checkBox = Xml::radio(
'mergepoint', $ts, ( $this->mTimestamp === $ts ) );
296 $revRecord->getPageAsLinkTarget(),
297 $this->getLanguage()->userTimeAndDate( $ts, $user ),
299 [
'oldid' => $revRecord->getId() ]
301 if ( $revRecord->isDeleted( RevisionRecord::DELETED_TEXT ) ) {
302 $pageLink =
'<span class="history-deleted">' . $pageLink .
'</span>';
306 if ( !RevisionRecord::userCanBitfield(
307 $revRecord->getVisibility(),
308 RevisionRecord::DELETED_TEXT,
311 $last = $this->
msg(
'last' )->escaped();
312 } elseif ( isset( $this->prevId[$row->rev_id] ) ) {
314 $revRecord->getPageAsLinkTarget(),
315 $this->msg(
'last' )->text(),
318 'diff' => $row->rev_id,
319 'oldid' => $this->prevId[$row->rev_id]
326 $size = $row->rev_len;
327 if ( $size !==
null ) {
332 return Html::rawElement(
'li', [],
333 $this->
msg(
'mergehistory-revisionrow' )
334 ->rawParams( $checkBox, $last, $pageLink, $userLink, $stxt, $comment )->escaped() );
350 # Get the titles directly from the IDs, in case the target page params
351 # were spoofed. The queries are done based on the IDs, so it's best to
352 # keep it consistent...
353 $targetTitle = Title::newFromID( $this->mTargetID );
354 $destTitle = Title::newFromID( $this->mDestID );
355 if ( $targetTitle ===
null || $destTitle ===
null ) {
358 if ( $targetTitle->getArticleID() == $destTitle->getArticleID() ) {
363 $factory = MediaWikiServices::getInstance()->getMergeHistoryFactory();
364 $mh = $factory->newMergeHistory( $targetTitle, $destTitle, $this->mTimestamp );
367 $mergeStatus = $mh->merge( $this->
getUser(), $this->mComment );
368 if ( !$mergeStatus->isOK() ) {
370 $this->
getOutput()->addWikiMsg( $mergeStatus->getMessage() );
380 [
'redirect' =>
'no' ]
383 $this->
getOutput()->addWikiMsg( $this->
msg(
'mergehistory-done' )
384 ->rawParams( $targetLink )
385 ->params( $destTitle->getPrefixedText() )
386 ->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( $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.
Class to simplify the use of log 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.