98 parent::__construct(
'MergeHistory',
'mergehistory' );
99 $this->mergeHistoryFactory = $mergeHistoryFactory;
100 $this->linkBatchFactory = $linkBatchFactory;
101 $this->dbProvider = $dbProvider;
102 $this->revisionStore = $revisionStore;
103 $this->commentFormatter = $commentFormatter;
104 $this->changeTagsStore = $changeTagsStore;
114 private function loadRequestParams() {
116 $this->mAction = $request->getRawVal(
'action' );
117 $this->mTarget = $request->getVal(
'target',
'' );
118 $this->mDest = $request->getVal(
'dest',
'' );
119 $this->mSubmitted = $request->getBool(
'submitted' );
121 $this->mTargetID = intval( $request->getVal(
'targetID' ) );
122 $this->mDestID = intval( $request->getVal(
'destID' ) );
123 $this->mTimestamp = $request->getVal(
'mergepoint' );
124 if ( $this->mTimestamp ===
null || !preg_match(
'/[0-9]{14}(\|[0-9]+)?/', $this->mTimestamp ) ) {
125 $this->mTimestamp =
'';
127 $this->mComment = $request->getText(
'wpComment' );
129 $this->mMerge = $request->wasPosted()
130 && $this->
getContext()->getCsrfTokenSet()->matchToken( $request->getVal(
'wpEditToken' ) );
133 if ( $this->mSubmitted ) {
134 $this->mTargetObj = Title::newFromText( $this->mTarget );
135 $this->mDestObj = Title::newFromText( $this->mDest );
137 $this->mTargetObj =
null;
138 $this->mDestObj =
null;
148 $this->loadRequestParams();
152 $status = Status::newGood();
154 if ( $this->mTargetID && $this->mDestID && $this->mAction ==
'submit' && $this->mMerge ) {
160 if ( !$this->mSubmitted ) {
161 $this->showMergeForm();
166 if ( !$this->mTargetObj instanceof
Title ) {
167 $status->merge( Status::newFatal(
'mergehistory-invalid-source' ) );
168 } elseif ( !$this->mTargetObj->exists() ) {
169 $status->merge( Status::newFatal(
170 'mergehistory-no-source',
175 if ( !$this->mDestObj instanceof
Title ) {
176 $status->merge( Status::newFatal(
'mergehistory-invalid-destination' ) );
177 } elseif ( !$this->mDestObj->exists() ) {
178 $status->merge( Status::newFatal(
179 'mergehistory-no-destination',
184 if ( $this->mTargetObj && $this->mDestObj && $this->mTargetObj->equals( $this->mDestObj ) ) {
185 $status->merge( Status::newFatal(
'mergehistory-same-destination' ) );
188 $this->mStatus = $status;
190 $this->showMergeForm();
192 if ( $this->mStatus->isGood() ) {
193 $this->showHistory();
197 private function showMergeForm() {
199 $out->addWikiMsg(
'mergehistory-header' );
205 'name' =>
'submitted'
215 'name' =>
'mergepoint'
219 'label-message' =>
'mergehistory-from',
226 'label-message' =>
'mergehistory-into',
233 $form = HTMLForm::factory(
'ooui', $fields, $this->
getContext() );
234 $form->setWrapperLegendMsg(
'mergehistory-box' )
235 ->setSubmitTextMsg(
'mergehistory-go' )
238 ->displayForm( $this->mStatus );
243 private function showHistory() {
244 # List all stored revisions
245 $revisions =
new MergeHistoryPager(
248 $this->linkBatchFactory,
250 $this->revisionStore,
251 $this->commentFormatter,
252 $this->changeTagsStore,
258 $haveRevisions = $revisions->getNumRows() > 0;
261 $out->addModuleStyles( [
262 'mediawiki.interface.helpers.styles',
266 $action = $titleObj->getLocalURL( [
'action' =>
'submit' ] );
267 # Start the form here
271 'name' =>
'targetID',
272 'default' => $this->mTargetObj->getArticleID()
277 'default' => $this->mDestObj->getArticleID()
290 if ( $haveRevisions ) {
294 'default' => $this->
msg(
'mergehistory-merge', $this->mTargetObj->getPrefixedText(),
295 $this->mDestObj->getPrefixedText() )->parse(),
297 'cssclass' =>
'mw-mergehistory-explanation',
298 'section' =>
'mergehistory-submit'
302 'name' =>
'wpComment',
303 'label-message' =>
'mergehistory-reason',
306 'section' =>
'mergehistory-submit'
310 'default' => $this->
msg(
'mergehistory-submit' ),
311 'section' =>
'mergehistory-submit',
312 'id' =>
'mw-merge-submit',
317 $form = HTMLForm::factory(
'ooui', $fields, $this->
getContext() );
318 $form->addHiddenField(
'wpEditToken', $form->getCsrfTokenSet()->getToken() )
320 ->setAction( $action )
321 ->suppressDefaultSubmit();
323 if ( $haveRevisions ) {
324 $form->setFooterHtml(
325 '<h2 id="mw-mergehistory">' . $this->
msg(
'mergehistory-list' )->escaped() .
'</h2>' .
326 $revisions->getNavigationBar() .
327 $revisions->getBody() .
328 $revisions->getNavigationBar()
331 $form->setFooterHtml( $this->
msg(
'mergehistory-empty' ) );
334 $form->prepareForm()->displayForm(
false );
336 # Show relevant lines from the merge log:
337 $mergeLogPage =
new LogPage(
'merge' );
338 $out->addHTML(
'<h2>' . $mergeLogPage->getName()->escaped() .
"</h2>\n" );
339 LogEventsList::showLogExtract( $out,
'merge', $this->mTargetObj );
354 private function merge() {
355 # Get the titles directly from the IDs, in case the target page params
356 # were spoofed. The queries are done based on the IDs, so it's best to
357 # keep it consistent...
358 $targetTitle = Title::newFromID( $this->mTargetID );
359 $destTitle = Title::newFromID( $this->mDestID );
360 if ( $targetTitle ===
null || $destTitle ===
null ) {
363 if ( $targetTitle->getArticleID() == $destTitle->getArticleID() ) {
368 $mh = $this->mergeHistoryFactory->newMergeHistory( $targetTitle, $destTitle, $this->mTimestamp );
371 $mergeStatus = $mh->merge( $this->
getAuthority(), $this->mComment );
372 if ( !$mergeStatus->isOK() ) {
374 $this->
getOutput()->addWikiMsg( $mergeStatus->getMessage() );
380 $targetLink = $linkRenderer->makeLink(
384 [
'redirect' =>
'no' ]
388 $append = ( $mergeStatus->getValue() ===
'source-deleted' )
389 ? $this->
msg(
'mergehistory-source-deleted', $targetTitle->getPrefixedText() ) :
'';
391 $this->
getOutput()->addWikiMsg( $this->
msg(
'mergehistory-done' )
392 ->rawParams( $targetLink )
393 ->params( $destTitle->getPrefixedText(), $append )
394 ->numParams( $mh->getMergedRevisionCount() )