ЧТМ:Расширения/PersonalWhitelist/WhitelistAction.php

Материал из ЧТМ
Перейти к навигации Перейти к поиску
<?php

namespace PersonalWhitelist;

use FormAction;
use HTMLForm;
use ManualLogEntry;

class WhitelistAction extends FormAction {

	public function getName() {
		return 'whitelist';
	}

	protected function getDescription() {
		return $this->msg( 'personalwhitelist-action-title' )->text();
	}

	protected function usesOOUI() {
		return true;
	}

	protected function checkCanExecute( \User $user ) {
		parent::checkCanExecute( $user );
		
		if ( !$user->isAllowed( 'editwhitelist-manage' ) ) {
			throw new \PermissionsError( 'editwhitelist-manage' );
		}

		if ( !$this->getTitle()->exists() ) {
			throw new \ErrorPageError( 'nosuchpage', 'nopagetext' );
		}
		
		if ( !$this->getTitle()->userCan( 'edit', $user ) ) {
			throw new \ErrorPageError(
				'personalwhitelist-cant-manage-title',
				'personalwhitelist-cant-manage-text'
			);
		}
	}

	protected function getFormFields() {
		$pageId = $this->getTitle()->getArticleID();
		
		$dbr = wfGetDB( DB_REPLICA );
		$prop = $dbr->selectField(
			'page_props',
			'pp_value',
			[ 'pp_page' => $pageId, 'pp_propname' => 'custom_whitelist' ],
			__METHOD__
		);

		$enabled = false;
		$usersText = '';
		$savedLevel = '';

		if ( $prop !== false ) {
			$data = json_decode( $prop, true );
			if ( $data ) {
				$enabled = !empty( $data['enabled'] );
				$usersText = implode( "\n", $data['users'] ?? [] );
				$savedLevel = $data['level'] ?? '';
			}
		}

		// ИСПРАВЛЕНИЕ ЗДЕСЬ: Получаем конфигурацию безопасным для MW 1.34 способом
		$config = \MediaWiki\MediaWikiServices::getInstance()->getMainConfig();
		$restrictionLevels = $config->get( 'RestrictionLevels' );
		$user = $this->getUser();
		
		// Опция по умолчанию (только белый список)
		$levelOptions = [
			$this->msg( 'personalwhitelist-level-none' )->text() => ''
		];

		foreach ( $restrictionLevels as $level ) {
			if ( $level !== '' ) {
				// Историческая особенность MediaWiki: уровни sysop и autoconfirmed
				// проверяются через права editprotected и editsemiprotected
				$reqRight = $level;
				if ( $level === 'sysop' ) {
					$reqRight = 'editprotected';
				} elseif ( $level === 'autoconfirmed' ) {
					$reqRight = 'editsemiprotected';
				}

				// Показываем ТОЛЬКО ТЕ уровни, к которым у участника есть реальные права
				if ( $user->isAllowed( $reqRight ) ) {
					$msg = wfMessage( "protect-level-{$level}" );
					$label = $msg->exists() ? $msg->text() : $level;
					$levelOptions[$label] = $level;
				}
			}
		}

		return [
			'intro' => [
				'type' => 'info',
				'raw' => true,
				'default' => $this->msg( 'personalwhitelist-form-intro' )->parse(),
			],
			'enabled' => [
				'type' => 'toggle',
				'label-message' => 'personalwhitelist-form-enabled',
				'default' => $enabled,
			],
			'level' => [
				'type' => 'select',
				'label-message' => 'personalwhitelist-form-level',
				'options' => $levelOptions,
				'default' => $savedLevel,
			],
			'users' => [
				'type' => 'textarea',
				'label-message' => 'personalwhitelist-form-users',
				'default' => $usersText,
				'rows' => 10,
			],
			'reason' => [
				'type' => 'text',
				'label-message' => 'personalwhitelist-form-reason',
			]
		];
	}

	protected function alterForm( HTMLForm $form ) {
		$form->setSubmitTextMsg( 'personalwhitelist-form-submit' );
	}

	public function onSubmit( $data ) {
		$pageId = $this->getTitle()->getArticleID();
		$dbw = wfGetDB( DB_MASTER );

		$rawUsers = explode( "\n", $data['users'] );
		$cleanUsers = [];
		foreach ( $rawUsers as $u ) {
			$u = trim( $u );
			if ( $u !== '' ) {
				$cleanUsers[] = $u;
			}
		}
		
		$cleanUsers = array_unique( $cleanUsers );
		$isEnabled = (bool)$data['enabled'];
		$level = $data['level'];

		// Если выключено, уровень пуст и список пуст - удаляем из БД
		if ( !$isEnabled && empty( $cleanUsers ) && $level === '' ) {
			$dbw->delete(
				'page_props',
				[ 'pp_page' => $pageId, 'pp_propname' => 'custom_whitelist' ],
				__METHOD__
			);
		} else {
			// Сохраняем в JSON вместе с новым полем 'level'
			$jsonData = json_encode( [
				'enabled' => $isEnabled,
				'level' => $level,
				'users' => array_values( $cleanUsers ) 
			] );

			$dbw->replace(
				'page_props',
				[ [ 'pp_page', 'pp_propname' ] ],
				[
					'pp_page' => $pageId,
					'pp_propname' => 'custom_whitelist',
					'pp_value' => $jsonData,
					'pp_sortkey' => null
				],
				__METHOD__
			);
		}

		$logEntry = new ManualLogEntry( 'whitelist', 'modify' );
		$logEntry->setPerformer( $this->getUser() );
		$logEntry->setTarget( $this->getTitle() );
		$logEntry->setComment( $data['reason'] );
		$logEntry->insert();

		return true;
	}

	public function onSuccess() {
		$url = $this->getTitle()->getFullURL( [ 'action' => 'whitelist', 'success' => 1 ] );
		$this->getOutput()->redirect( $url );
	}

	public function show() {
		if ( $this->getRequest()->getBool( 'success' ) ) {
			$msg = $this->msg( 'personalwhitelist-saved' )->text();
			$this->getOutput()->addHTML( \Html::successBox( $msg ) );
		}
		parent::show();
	}
}