29 private ?Title $title;
32 private string $reason;
34 private bool $doSubpages =
false;
36 private ?
string $code;
37 private PermissionManager $permissionManager;
40 private string $entityType;
41 private const PAGE_TITLE_MSG = [
42 'messagebundle' =>
'pt-deletepage-mb-title',
43 'translatablepage' =>
'pt-deletepage-tp-title',
44 'translationpage' =>
'pt-deletepage-lang-title'
46 private const WRAPPER_LEGEND_MSG = [
47 'messagebundle' =>
'pt-deletepage-mb-legend',
48 'translatablepage' =>
'pt-deletepage-tp-title',
49 'translationpage' =>
'pt-deletepage-tp-legend'
51 private const LOG_PAGE = [
52 'messagebundle' =>
'Special:Log/messagebundle',
53 'translatablepage' =>
'Special:Log/pagetranslation',
54 'translationpage' =>
'Special:Log/pagetranslation'
57 public function __construct(
58 PermissionManager $permissionManager,
62 parent::__construct(
'PageTranslationDeletePage',
'pagetranslation' );
63 $this->permissionManager = $permissionManager;
64 $this->bundleFactory = $bundleFactory;
65 $this->bundleDeleter = $bundleDeleter;
68 public function doesWrites() {
72 public function execute( $par ) {
73 $this->addHelpLink(
'Help:Deletion_and_undeletion' );
75 $request = $this->getRequest();
80 $this->text = $request->getVal(
'wpTitle', $par );
81 $this->title = Title::newFromText( $this->text );
82 $this->reason = $this->getDeleteReason( $request );
83 $this->doSubpages = $request->getBool(
'subpages' );
85 if ( !$this->doBasicChecks() ) {
89 $out = $this->getOutput();
92 $entityType = $this->identifyEntityType();
94 throw new ErrorPageError(
'pt-deletepage-invalid-title',
'pt-deletepage-invalid-text' );
96 $this->entityType = $entityType;
98 if ( $this->isTranslation() ) {
104 $out->setPageTitleMsg(
105 $this->msg( self::PAGE_TITLE_MSG[ $this->entityType ], $this->title->getPrefixedText() )
108 if ( !$this->getUser()->isAllowed(
'pagetranslation' ) ) {
109 throw new PermissionsError(
'pagetranslation' );
113 $subactionText = $request->getText(
'subaction' );
114 switch ( $subactionText ) {
115 case $this->msg(
'pt-deletepage-action-check' )->text():
116 $subaction =
'check';
118 case $this->msg(
'pt-deletepage-action-perform' )->text():
119 $subaction =
'perform';
121 case $this->msg(
'pt-deletepage-action-other' )->text():
128 if ( $subaction ===
'check' && $this->checkToken() && $request->wasPosted() ) {
129 $this->showConfirmation();
130 } elseif ( $subaction ===
'perform' && $this->checkToken() && $request->wasPosted() ) {
131 $this->performAction();
142 private function doBasicChecks():
bool {
144 if ( !$this->userCanExecute( $this->getUser() ) ) {
145 $this->displayRestrictionError();
148 if ( $this->title ===
null ) {
149 throw new ErrorPageError(
'notargettitle',
'notargettext' );
152 if ( !$this->title->exists() ) {
153 throw new ErrorPageError(
'nopagetitle',
'nopagetext' );
156 $permissionStatus = $this->permissionManager->getPermissionStatus(
157 'delete', $this->getUser(), $this->title
159 if ( !$permissionStatus->isOK() ) {
160 throw new PermissionsError(
'delete', $permissionStatus );
163 # Check for database lock
164 $this->checkReadOnly();
174 private function checkToken():
bool {
175 return $this->getContext()->getCsrfTokenSet()->matchTokenField(
'wpEditToken' );
179 private function showForm():
void {
180 $out = $this->getOutput();
181 $out->addBacklinkSubtitle( $this->title );
182 $out->addWikiMsg(
'pt-deletepage-intro', self::LOG_PAGE[ $this->entityType ] );
184 $formDescriptor = $this->getCommonFormFields();
186 HTMLForm::factory(
'ooui', $formDescriptor, $this->getContext() )
187 ->setAction( $this->getPageTitle( $this->text )->getLocalURL() )
188 ->setSubmitName(
'subaction' )
189 ->setSubmitTextMsg(
'pt-deletepage-action-check' )
190 ->setWrapperLegendMsg(
'pt-deletepage-any-legend' )
192 ->displayForm(
false );
199 private function showConfirmation():
void {
200 $out = $this->getOutput();
204 $out->addBacklinkSubtitle( $this->title );
205 $out->addWikiMsg(
'pt-deletepage-intro', self::LOG_PAGE[ $this->entityType ] );
207 $subpages = $this->bundleDeleter->getPagesForDeletion( $this->title, $this->code, $this->isTranslation() );
209 $out->wrapWikiMsg(
'== $1 ==',
'pt-deletepage-list-pages' );
211 if ( !$this->isTranslation() ) {
213 $out->addWikiTextAsInterface(
214 $this->getChangeLine( $this->title )
218 $out->wrapWikiMsg(
'=== $1 ===',
'pt-deletepage-list-translation' );
220 foreach ( $subpages[
'translationPages' ] as $old ) {
222 $lines[] = $this->getChangeLine( $old );
224 $this->listPages( $out, $lines );
226 $out->wrapWikiMsg(
'=== $1 ===',
'pt-deletepage-list-section' );
229 foreach ( $subpages[
'translationUnitPages' ] as $old ) {
231 $lines[] = $this->getChangeLine( $old );
233 $this->listPages( $out, $lines );
235 if ( Utilities::allowsSubpages( $this->title ) ) {
236 $out->wrapWikiMsg(
'=== $1 ===',
'pt-deletepage-list-other' );
237 $subpages = $subpages[
'normalSubpages' ];
239 foreach ( $subpages as $old ) {
241 $lines[] = $this->getChangeLine( $old );
243 $this->listPages( $out, $lines );
246 $totalPageCount = $count + $subpageCount;
248 $out->addWikiTextAsInterface(
"----\n" );
250 'pt-deletepage-list-count',
251 $this->getLanguage()->formatNum( $totalPageCount ),
252 $this->getLanguage()->formatNum( $subpageCount )
255 $formDescriptor = $this->getCommonFormFields();
256 $formDescriptor[
'subpages'] = [
258 'name' =>
'subpages',
259 'id' =>
'mw-subpages',
260 'label' => $this->msg(
'pt-deletepage-subpages' )->text(),
261 'default' => $this->doSubpages,
264 $htmlForm = HTMLForm::factory(
'ooui', $formDescriptor, $this->getContext() );
266 ->setWrapperLegendMsg(
267 $this->msg( self::WRAPPER_LEGEND_MSG[ $this->entityType ], $this->title->getPrefixedText() )
269 ->setAction( $this->getPageTitle( $this->text )->getLocalURL() )
270 ->setSubmitTextMsg(
'pt-deletepage-action-perform' )
271 ->setSubmitName(
'subaction' )
272 ->setSubmitDestructive()
274 'name' =>
'subaction',
275 'value' => $this->msg(
'pt-deletepage-action-other' )->text(),
278 ->displayForm(
false );
282 private function getChangeLine( Title $title ):
string {
283 return '* ' . $title->getPrefixedText();
286 private function performAction():
void {
287 $this->bundleDeleter->deleteAsynchronously(
289 $this->isTranslation(),
291 $this->bundleDeleter->getPagesForDeletion( $this->title, $this->code, $this->isTranslation() ),
296 $this->getOutput()->addWikiMsg(
'pt-deletepage-started', self::LOG_PAGE[ $this->entityType ] );
299 private function getCommonFormFields(): array {
300 $dropdownOptions = $this->msg(
'deletereason-dropdown' )->inContentLanguage()->text();
302 $options = Html::listDropdownOptions(
305 'other' => $this->msg(
'pt-deletepage-reason-other' )->inContentLanguage()->text()
313 'label-message' =>
'pt-deletepage-current',
315 'default' => $this->title->getPrefixedText(),
318 'wpDeleteReasonList' => [
320 'name' =>
'wpDeleteReasonList',
321 'label-message' =>
'pt-deletepage-reason',
322 'options' => $options,
326 'name' =>
'wpReason',
327 'label-message' =>
'pt-deletepage-reason-details',
328 'default' => $this->reason,
333 private function listPages( OutputPage $out, array $lines ):
void {
335 $out->addWikiTextAsInterface( implode(
"\n", $lines ) );
337 $out->addWikiMsg(
'pt-deletepage-list-no-pages' );
341 private function getDeleteReason( WebRequest $request ):
string {
342 $dropdownSelection = $request->getText(
'wpDeleteReasonList',
'other' );
343 $reasonInput = $request->getText(
'wpReason' );
345 if ( $dropdownSelection ===
'other' ) {
347 } elseif ( $reasonInput !==
'' ) {
349 $separator = $this->msg(
'colon-separator' )->inContentLanguage()->text();
350 return "$dropdownSelection$separator$reasonInput";
352 return $dropdownSelection;
357 private function identifyEntityType(): ?
string {
358 $bundle = $this->bundleFactory->getBundle( $this->title );
361 return 'messagebundle';
363 return 'translatablepage';
366 return 'translationpage';
372 private function isTranslation():
bool {
373 return $this->entityType ===
'translationpage';