99 $this->mArticle = $article;
100 $this->mTitle = $article->
getTitle();
101 $this->mApplicableTypes = $this->mTitle->getRestrictionTypes();
103 $this->mRequest = $this->mContext->getRequest();
104 $this->mUser = $this->mContext->getUser();
105 $this->mOut = $this->mContext->getOutput();
106 $this->mLang = $this->mContext->getLanguage();
108 $services = MediaWikiServices::getInstance();
109 $this->permManager = $services->getPermissionManager();
110 $this->hookRunner =
new HookRunner( $services->getHookContainer() );
114 $this->mPermErrors = $this->permManager->getPermissionErrors(
118 $this->mRequest->wasPosted()
119 ? PermissionManager::RIGOR_SECURE
120 : PermissionManager::RIGOR_FULL
125 $this->disabled = $this->mPermErrors !== [];
126 $this->disabledAttrib = $this->disabled ? [
'disabled' =>
'disabled' ] : [];
135 $levels = $this->permManager->getNamespaceRestrictionLevels(
136 $this->mTitle->getNamespace(), $this->mUser
139 $this->mCascade = $this->mTitle->areRestrictionsCascading();
140 $this->mReason = $this->mRequest->getText(
'mwProtect-reason' );
141 $this->mReasonSelection = $this->mRequest->getText(
'wpProtectReasonSelection' );
142 $this->mCascade = $this->mRequest->getBool(
'mwProtect-cascade', $this->mCascade );
144 foreach ( $this->mApplicableTypes as $action ) {
149 $this->mRestrictions[$action] = implode(
'', $this->mTitle->getRestrictions( $action ) );
151 if ( !$this->mRestrictions[$action] ) {
153 $existingExpiry =
'';
155 $existingExpiry = $this->mTitle->getRestrictionExpiry( $action );
157 $this->mExistingExpiry[$action] = $existingExpiry;
159 $requestExpiry = $this->mRequest->getText(
"mwProtect-expiry-$action" );
160 $requestExpirySelection = $this->mRequest->getVal(
"wpProtectExpirySelection-$action" );
162 if ( $requestExpiry ) {
164 $this->mExpiry[$action] = $requestExpiry;
165 $this->mExpirySelection[$action] =
'othertime';
166 } elseif ( $requestExpirySelection ) {
168 $this->mExpiry[$action] =
'';
169 $this->mExpirySelection[$action] = $requestExpirySelection;
170 } elseif ( $existingExpiry ) {
172 $this->mExpiry[$action] =
'';
173 $this->mExpirySelection[$action] = $existingExpiry;
177 $this->mExpiry[$action] =
'';
178 $this->mExpirySelection[$action] =
'infinite';
181 $val = $this->mRequest->getVal(
"mwProtect-level-$action" );
182 if ( isset( $val ) && in_array( $val, $levels ) ) {
183 $this->mRestrictions[$action] = $val;
246 private function show( $err =
null ) {
249 $out->addBacklinkSubtitle( $this->mTitle );
251 if ( is_array( $err ) ) {
252 $out->wrapWikiMsg(
"<div class='error'>\n$1\n</div>\n", $err );
253 } elseif ( is_string( $err ) ) {
254 $out->addHTML(
"<div class='error'>{$err}</div>\n" );
257 if ( $this->mApplicableTypes === [] ) {
260 $out->setPageTitle( $this->mContext->msg(
261 'protect-norestrictiontypes-title',
262 $this->mTitle->getPrefixedText()
264 $out->addWikiTextAsInterface(
265 $this->mContext->msg(
'protect-norestrictiontypes-text' )->plain()
274 list( $cascadeSources, ) = $this->mTitle->getCascadeProtectionSources();
275 if ( $cascadeSources && count( $cascadeSources ) > 0 ) {
278 foreach ( $cascadeSources as
$title ) {
279 $titles .=
'* [[:' .
$title->getPrefixedText() .
"]]\n";
284 "<div id=\"mw-protect-cascadeon\">\n$1\n" . $titles .
"</div>",
285 [
'protect-cascadeon', count( $cascadeSources ) ]
289 # Show an appropriate message if the user isn't allowed or able to change
290 # the protection settings at this time
291 if ( $this->disabled ) {
293 $this->mContext->msg(
'protect-title-notallowed',
294 $this->mTitle->getPrefixedText() )
296 $out->addWikiTextAsInterface( $out->formatPermissionsErrorMessage(
297 $this->mPermErrors,
'protect'
301 $this->mContext->msg(
'protect-title', $this->mTitle->getPrefixedText() )
303 $out->addWikiMsg(
'protect-text',
318 if ( $this->disabled ) {
323 $token = $this->mRequest->getVal(
'wpEditToken' );
324 if ( !$this->mUser->matchEditToken( $token, [
'protect', $this->mTitle->getPrefixedDBkey() ] ) ) {
325 $this->
show( [
'sessionfailure' ] );
329 # Create reason string. Use list and/or custom string.
331 if ( $reasonstr !=
'other' && $this->mReason !=
'' ) {
333 $reasonstr .= $this->mContext->msg(
'colon-separator' )->text() .
$this->mReason;
334 } elseif ( $reasonstr ==
'other' ) {
339 foreach ( $this->mApplicableTypes as $action ) {
340 $expiry[$action] = $this->
getExpiry( $action );
341 if ( empty( $this->mRestrictions[$action] ) ) {
345 if ( !$expiry[$action] ) {
346 $this->
show( [
'protect_expiry_invalid' ] );
350 $this->
show( [
'protect_expiry_old' ] );
355 $this->mCascade = $this->mRequest->getBool(
'mwProtect-cascade' );
357 $status = $this->mArticle->getPage()->doUpdateRestrictions(
358 $this->mRestrictions,
365 if ( !$status->isOK() ) {
366 $this->
show( $this->mOut->parseInlineAsInterface(
367 $status->getWikiText(
false,
false, $this->mLang )
379 if ( !$this->hookRunner->onProtectionForm__save( $this->mArticle, $errorMsg, $reasonstr ) ) {
380 if ( $errorMsg ==
'' ) {
381 $errorMsg = [
'hookaborted' ];
384 if ( $errorMsg !=
'' ) {
385 $this->
show( $errorMsg );
390 $this->mRequest->getCheck(
'mwProtectWatch' ),
404 $this->mOut->enableOOUI();
407 if ( !$this->disabled ) {
408 $this->mOut->addModules(
'mediawiki.action.protect' );
409 $this->mOut->addModuleStyles(
'mediawiki.action.styles' );
411 $scExpiryOptions = $this->mContext->msg(
'protect-expiry-options' )->inContentLanguage()->text();
412 $levels = $this->permManager->getNamespaceRestrictionLevels(
413 $this->mTitle->getNamespace(),
418 foreach ( $this->mRestrictions as $action => $selected ) {
421 $section =
'restriction-' . $action;
422 $id =
'mwProtect-level-' . $action;
424 foreach ( $levels as $key ) {
431 'default' => $selected,
433 'size' => count( $levels ),
434 'options' => $options,
436 'section' => $section,
441 if ( $this->mExistingExpiry[$action] ) {
442 if ( $this->mExistingExpiry[$action] ==
'infinity' ) {
443 $existingExpiryMessage = $this->mContext->msg(
'protect-existing-expiry-infinity' );
445 $timestamp = $this->mLang->userTimeAndDate( $this->mExistingExpiry[$action], $this->mUser );
446 $date = $this->mLang->userDate( $this->mExistingExpiry[$action], $this->mUser );
447 $time = $this->mLang->userTime( $this->mExistingExpiry[$action], $this->mUser );
448 $existingExpiryMessage = $this->mContext->msg(
449 'protect-existing-expiry',
455 $expiryOptions[$existingExpiryMessage->text()] =
'existing';
458 $expiryOptions[$this->mContext->msg(
'protect-othertime-op' )->text()] =
'othertime';
459 foreach ( explode(
',', $scExpiryOptions ) as $option ) {
460 if ( strpos( $option,
":" ) ===
false ) {
461 $show = $value = $option;
463 list( $show, $value ) = explode(
":", $option );
465 $expiryOptions[$show] = htmlspecialchars( $value );
468 # Add expiry dropdown
469 $fields[
"wpProtectExpirySelection-$action"] = [
471 'name' =>
"wpProtectExpirySelection-$action",
472 'id' =>
"mwProtectExpirySelection-$action",
475 'label' => $this->mContext->msg(
'protectexpiry' )->text(),
476 'options' => $expiryOptions,
477 'default' => $this->mExpirySelection[$action],
478 'section' => $section,
481 # Add custom expiry field
482 if ( !$this->disabled ) {
483 $fields[
"mwProtect-expiry-$action"] = [
485 'label' => $this->mContext->msg(
'protect-othertime' )->text(),
486 'name' =>
"mwProtect-expiry-$action",
487 'id' =>
"mwProtect-$action-expires",
489 'default' => $this->mExpiry[$action],
491 'section' => $section,
496 # Give extensions a chance to add items to the form
498 $hookFormOptions = [];
500 $this->hookRunner->onProtectionForm__buildForm( $this->mArticle, $hookFormRaw );
501 $this->hookRunner->onProtectionFormAddFormFields( $this->mArticle, $hookFormOptions );
503 # Merge forms added from addFormFields
504 $fields = array_merge( $fields, $hookFormOptions );
506 # Add raw sections added in buildForm
507 if ( $hookFormRaw ) {
508 $fields[
'rawinfo'] = [
510 'default' => $hookFormRaw,
512 'section' =>
'restriction-blank'
516 # JavaScript will add another row with a value-chaining checkbox
517 if ( $this->mTitle->exists() ) {
518 $fields[
'mwProtect-cascade'] = [
520 'label' => $this->mContext->msg(
'protect-cascade' )->text(),
521 'id' =>
'mwProtect-cascade',
522 'name' =>
'mwProtect-cascade',
528 # Add manual and custom reason field/selects as well as submit
529 if ( !$this->disabled ) {
535 $maxlength = CommentStore::COMMENT_CHARACTER_LIMIT - 75;
536 $fields[
'wpProtectReasonSelection'] = [
538 'cssclass' =>
'mwProtect-reason',
539 'label' => $this->mContext->msg(
'protectcomment' )->text(),
541 'id' =>
'wpProtectReasonSelection',
542 'name' =>
'wpProtectReasonSelection',
544 'options' => Xml::listDropDownOptions(
545 $this->mContext->msg(
'protect-dropdown' )->inContentLanguage()->text(),
546 [
'other' => $this->mContext->msg(
'protect-otherreason-op' )->inContentLanguage()->text() ]
550 $fields[
'mwProtect-reason'] = [
552 'id' =>
'mwProtect-reason',
553 'label' => $this->mContext->msg(
'protect-otherreason' )->text(),
554 'name' =>
'mwProtect-reason',
556 'maxlength' => $maxlength,
559 # Disallow watching if user is not logged in
560 if ( $this->mUser->isRegistered() ) {
561 $fields[
'mwProtectWatch'] = [
563 'id' =>
'mwProtectWatch',
564 'label' => $this->mContext->msg(
'watchthis' )->text(),
565 'name' =>
'mwProtectWatch',
567 $this->mUser->isWatched( $this->mTitle )
568 || $this->mUser->getOption(
'watchdefault' )
574 if ( $this->permManager->userHasRight( $this->mUser,
'editinterface' ) ) {
575 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
576 $link = $linkRenderer->makeKnownLink(
577 $this->mContext->msg(
'protect-dropdown' )->inContentLanguage()->getTitle(),
578 $this->mContext->msg(
'protect-edit-reasonlist' )->text(),
580 [
'action' =>
'edit' ]
582 $out .=
'<p class="mw-protect-editreasons">' . $link .
'</p>';
585 if ( !$this->disabled ) {
586 $fields[
'wpEditToken'] = [
587 'name' =>
'wpEditToken',
589 'default' => $this->mUser->getEditToken( [
'protect', $this->mTitle->getPrefixedDBkey() ] ),
593 $htmlForm = HTMLForm::factory(
'ooui', $fields, $this->mContext );
595 ->setMethod(
'post' )
596 ->setId(
'mw-Protect-Form' )
597 ->setTableId(
'mw-protect-table2' )
598 ->setAction( $this->mTitle->getLocalURL(
'action=protect' ) )
599 ->setSubmitID(
'mw-Protect-submit' )
600 ->setSubmitText( $this->mContext->msg(
'confirm' )->text() )
601 ->suppressDefaultSubmit( $this->disabled )
602 ->setWrapperLegend( $this->mContext->msg(
'protect-legend' )->text() )
605 return $htmlForm->getHTML(
false ) . $out;