mediawiki-extensions-Echo/includes/Special/SpecialNotificationsMarkRead.php
Ammarpad 4303ab5f71 special: Check login permissions before calling execute method
Calling the parent method first means the form has to be built (as
well as various other things) and then it cannot be shown because
of permission and the user is redirected.

This also lead to confusing behavior where some code paths are
reached even though the user cannot actually access the page.

Change-Id: If354d98f9e51acef38cac114a7704d28c148017b
2024-10-27 10:03:09 +01:00

155 lines
4 KiB
PHP

<?php
namespace MediaWiki\Extension\Notifications\Special;
use MediaWiki\Extension\Notifications\NotifUser;
use MediaWiki\HTMLForm\HTMLForm;
use MediaWiki\SpecialPage\FormSpecialPage;
use MediaWiki\SpecialPage\SpecialPage;
/**
* Form for marking notifications as read by ID.
*
* This uses the normal HTMLForm handling when receiving POSTs.
* However, for a better user no-JS user experience, we integrate
* a version of the form into Special:Notifications. Thus, this
* page should normally not need to be visited directly.
*/
class SpecialNotificationsMarkRead extends FormSpecialPage {
public function __construct() {
parent::__construct( 'NotificationsMarkRead' );
}
public function doesWrites() {
return true;
}
public function execute( $par ) {
// Redirect to login page and inform user of the need to login
$this->requireLogin( 'echo-notification-loginrequired' );
parent::execute( $par );
$out = $this->getOutput();
$out->setPageTitleMsg( $this->msg( 'echo-specialpage-markasread' ) );
}
public function isListed() {
return false;
}
public function getDisplayFormat() {
return 'ooui';
}
/**
* Get an HTMLForm descriptor array
* @return array[]
*/
protected function getFormFields() {
return [
'id' => [
'type' => 'hidden',
'required' => true,
'default' => $this->par,
'filter-callback' => static function ( $value, $alldata ) {
// Allow for a single value or a set of values
return explode( ',', $value ?? '' );
},
'validation-callback' => function ( $value, $alldata ) {
if ( $value === [ 'ALL' ] ) {
return true;
}
if ( (int)$value <= 0 ) {
return $this->msg( 'echo-specialpage-markasread-invalid-id' );
}
foreach ( $value as $val ) {
if ( (int)( $val ) <= 0 ) {
return $this->msg( 'echo-specialpage-markasread-invalid-id' );
}
}
return true;
}
]
];
}
/**
* Gets a pre-filled version of the form; this should not have a legend or anything
* visible, except the button.
*
* @param int|array $idValue ID or array of IDs
* @param string $submitButtonValue Value attribute for button
* @param bool $framed Whether the button should be framed
* @param string $submitLabelHtml Raw HTML to use for button label
*
* @return HTMLForm
*/
public function getMinimalForm( $idValue, $submitButtonValue, $framed, $submitLabelHtml ) {
if ( !is_array( $idValue ) ) {
$idValue = [ $idValue ];
}
$idString = implode( ',', $idValue );
$this->setParameter( $idString );
$form = HTMLForm::factory(
$this->getDisplayFormat(),
$this->getFormFields(),
$this->getContext(),
$this->getMessagePrefix()
);
// HTMLForm assumes that the main submit button is always 'primary',
// which means it is colored. Since this form is being embedded multiple
// places on the page, it has to be neutral, so we make the button
// manually.
$form->suppressDefaultSubmit();
$form->setTitle( $this->getPageTitle() );
$form->addButton( [
'name' => 'submit',
'value' => $submitButtonValue,
'label-raw' => $submitLabelHtml,
'framed' => $framed,
] );
return $form;
}
/**
* Sets a custom label
*
* This is only called when the form is actually visited directly, which is not the
* main intended use.
* @param HTMLForm $form
*/
protected function alterForm( HTMLForm $form ) {
$form->setSubmitText( $this->msg( 'echo-notification-markasread' )->text() );
}
/**
* Process the form on POST submission.
* @param array $data
* @return bool
*/
public function onSubmit( array $data ) {
$notifUser = NotifUser::newFromUser( $this->getUser() );
// Allow for all IDs
if ( $data['id'] === [ 'ALL' ] ) {
return $notifUser->markAllRead();
}
// Allow for multiple IDs or a single ID
$ids = $data['id'];
return $notifUser->markRead( $ids );
}
public function onSuccess() {
$page = SpecialPage::getTitleFor( 'Notifications' );
$this->getOutput()->redirect( $page->getFullURL() );
}
}