2020-11-24 12:16:41 +00:00
|
|
|
<?php
|
|
|
|
|
2021-02-01 15:47:46 +00:00
|
|
|
namespace MediaWiki\Extension\AbuseFilter\EditBox;
|
2020-11-24 12:16:41 +00:00
|
|
|
|
2021-02-01 15:47:46 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\AbuseFilterPermissionManager;
|
|
|
|
use MediaWiki\Extension\AbuseFilter\KeywordsManager;
|
2024-03-29 12:40:23 +00:00
|
|
|
use MediaWiki\Html\Html;
|
2023-12-10 19:03:19 +00:00
|
|
|
use MediaWiki\Output\OutputPage;
|
2022-05-27 09:41:54 +00:00
|
|
|
use MediaWiki\Permissions\Authority;
|
2020-11-24 12:16:41 +00:00
|
|
|
use MessageLocalizer;
|
2020-11-27 22:53:07 +00:00
|
|
|
use OOUI\ButtonWidget;
|
|
|
|
use OOUI\DropdownInputWidget;
|
|
|
|
use OOUI\FieldLayout;
|
|
|
|
use OOUI\FieldsetLayout;
|
|
|
|
use OOUI\Widget;
|
2020-11-24 12:16:41 +00:00
|
|
|
|
|
|
|
/**
|
2021-03-04 11:24:20 +00:00
|
|
|
* Base class for classes responsible for building filter edit boxes
|
2020-11-24 12:16:41 +00:00
|
|
|
*/
|
2021-03-04 11:24:20 +00:00
|
|
|
abstract class EditBoxBuilder {
|
2020-11-24 12:16:41 +00:00
|
|
|
/** @var AbuseFilterPermissionManager */
|
2021-03-04 11:24:20 +00:00
|
|
|
protected $afPermManager;
|
2020-11-24 12:16:41 +00:00
|
|
|
|
|
|
|
/** @var KeywordsManager */
|
2021-03-04 11:24:20 +00:00
|
|
|
protected $keywordsManager;
|
2020-11-24 12:16:41 +00:00
|
|
|
|
|
|
|
/** @var MessageLocalizer */
|
2021-03-04 11:24:20 +00:00
|
|
|
protected $localizer;
|
2020-11-24 12:16:41 +00:00
|
|
|
|
2022-05-27 09:41:54 +00:00
|
|
|
/** @var Authority */
|
|
|
|
protected $authority;
|
2020-11-24 12:16:41 +00:00
|
|
|
|
|
|
|
/** @var OutputPage */
|
2021-03-04 11:24:20 +00:00
|
|
|
protected $output;
|
2020-11-24 12:16:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @param AbuseFilterPermissionManager $afPermManager
|
|
|
|
* @param KeywordsManager $keywordsManager
|
|
|
|
* @param MessageLocalizer $messageLocalizer
|
2022-05-27 09:41:54 +00:00
|
|
|
* @param Authority $authority
|
2020-11-24 12:16:41 +00:00
|
|
|
* @param OutputPage $output
|
|
|
|
*/
|
|
|
|
public function __construct(
|
|
|
|
AbuseFilterPermissionManager $afPermManager,
|
|
|
|
KeywordsManager $keywordsManager,
|
|
|
|
MessageLocalizer $messageLocalizer,
|
2022-05-27 09:41:54 +00:00
|
|
|
Authority $authority,
|
2020-11-24 12:16:41 +00:00
|
|
|
OutputPage $output
|
|
|
|
) {
|
|
|
|
$this->afPermManager = $afPermManager;
|
|
|
|
$this->keywordsManager = $keywordsManager;
|
|
|
|
$this->localizer = $messageLocalizer;
|
2022-05-27 09:41:54 +00:00
|
|
|
$this->authority = $authority;
|
2020-11-24 12:16:41 +00:00
|
|
|
$this->output = $output;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $rules
|
|
|
|
* @param bool $addResultDiv
|
|
|
|
* @param bool $externalForm
|
|
|
|
* @param bool $needsModifyRights
|
|
|
|
* @param-taint $rules none
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function buildEditBox(
|
|
|
|
string $rules,
|
|
|
|
bool $addResultDiv = true,
|
|
|
|
bool $externalForm = false,
|
|
|
|
bool $needsModifyRights = true
|
2021-07-21 18:51:12 +00:00
|
|
|
): string {
|
2020-11-27 22:53:07 +00:00
|
|
|
$this->output->addModules( 'ext.abuseFilter.edit' );
|
2021-03-04 11:24:20 +00:00
|
|
|
$this->output->enableOOUI();
|
2020-11-24 12:16:41 +00:00
|
|
|
|
|
|
|
$isUserAllowed = $needsModifyRights ?
|
2022-05-27 09:41:54 +00:00
|
|
|
$this->afPermManager->canEdit( $this->authority ) :
|
|
|
|
$this->afPermManager->canUseTestTools( $this->authority );
|
2020-11-24 12:16:41 +00:00
|
|
|
if ( !$isUserAllowed ) {
|
|
|
|
$addResultDiv = false;
|
|
|
|
}
|
|
|
|
|
2021-03-04 11:24:20 +00:00
|
|
|
$output = $this->getEditBox( $rules, $isUserAllowed, $externalForm );
|
2020-11-24 12:16:41 +00:00
|
|
|
|
|
|
|
if ( $isUserAllowed ) {
|
2024-03-09 14:44:59 +00:00
|
|
|
$dropdown = $this->getSuggestionsDropdown();
|
2020-11-24 12:16:41 +00:00
|
|
|
|
2021-03-04 11:24:20 +00:00
|
|
|
$formElements = [
|
2024-03-09 14:44:59 +00:00
|
|
|
new FieldLayout( $dropdown ),
|
2021-03-04 11:24:20 +00:00
|
|
|
new FieldLayout( $this->getEditorControls() )
|
|
|
|
];
|
2020-11-24 12:16:41 +00:00
|
|
|
|
2020-11-27 22:53:07 +00:00
|
|
|
$fieldSet = new FieldsetLayout( [
|
2020-11-24 12:16:41 +00:00
|
|
|
'items' => $formElements,
|
|
|
|
'classes' => [ 'mw-abusefilter-edit-buttons', 'mw-abusefilter-javascript-tools' ]
|
|
|
|
] );
|
|
|
|
|
2021-03-04 11:24:20 +00:00
|
|
|
$output .= $fieldSet;
|
2020-11-24 12:16:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( $addResultDiv ) {
|
2024-03-29 12:40:23 +00:00
|
|
|
$output .= Html::element(
|
2020-11-27 22:53:07 +00:00
|
|
|
'div',
|
2024-05-13 11:15:27 +00:00
|
|
|
[ 'id' => 'mw-abusefilter-syntaxresult', 'style' => 'display: none;' ]
|
2020-11-27 22:53:07 +00:00
|
|
|
);
|
2020-11-24 12:16:41 +00:00
|
|
|
}
|
|
|
|
|
2021-03-04 11:24:20 +00:00
|
|
|
return $output;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return DropdownInputWidget
|
|
|
|
*/
|
2021-07-21 18:51:12 +00:00
|
|
|
private function getSuggestionsDropdown(): DropdownInputWidget {
|
2024-03-09 14:44:59 +00:00
|
|
|
$rawDropdown = $this->keywordsManager->getBuilderValues();
|
2021-03-04 11:24:20 +00:00
|
|
|
|
|
|
|
// The array needs to be rearranged to be understood by OOUI. It comes with the format
|
|
|
|
// [ group-msg-key => [ text-to-add => text-msg-key ] ] and we need it as
|
|
|
|
// [ group-msg => [ text-msg => text-to-add ] ]
|
|
|
|
// Also, the 'other' element must be the first one.
|
2024-03-09 14:44:59 +00:00
|
|
|
$dropdownOptions = [ $this->localizer->msg( 'abusefilter-edit-builder-select' )->text() => 'other' ];
|
|
|
|
foreach ( $rawDropdown as $group => $values ) {
|
2021-03-04 11:24:20 +00:00
|
|
|
// Give grep a chance to find the usages:
|
2024-05-03 16:27:58 +00:00
|
|
|
// abusefilter-edit-builder-group-op-arithmetic
|
|
|
|
// abusefilter-edit-builder-group-op-comparison
|
|
|
|
// abusefilter-edit-builder-group-op-bool
|
|
|
|
// abusefilter-edit-builder-group-misc
|
|
|
|
// abusefilter-edit-builder-group-funcs
|
|
|
|
// abusefilter-edit-builder-group-vars
|
2021-03-04 11:24:20 +00:00
|
|
|
$localisedGroup = $this->localizer->msg( "abusefilter-edit-builder-group-$group" )->text();
|
2024-03-09 14:44:59 +00:00
|
|
|
$dropdownOptions[ $localisedGroup ] = array_flip( $values );
|
2021-03-04 11:24:20 +00:00
|
|
|
$newKeys = array_map(
|
2024-05-03 16:27:58 +00:00
|
|
|
function ( $key ) use ( $group, $dropdownOptions, $localisedGroup ) {
|
|
|
|
// Force all operators and functions to be always shown as left to right text
|
|
|
|
// with the help of control characters:
|
|
|
|
// * 202A is LEFT-TO-RIGHT EMBEDDING (LRE)
|
|
|
|
// * 202C is POP DIRECTIONAL FORMATTING (PDF)
|
|
|
|
// This has to be done with control characters because
|
|
|
|
// markup cannot be used within <option> elements.
|
|
|
|
$operatorExample = "\u{202A}" .
|
|
|
|
$dropdownOptions[ $localisedGroup ][ $key ] .
|
|
|
|
"\u{202C}";
|
|
|
|
return $this->localizer->msg(
|
|
|
|
"abusefilter-edit-builder-$group-$key",
|
|
|
|
$operatorExample
|
|
|
|
)->text();
|
2021-03-04 11:24:20 +00:00
|
|
|
},
|
2024-03-09 14:44:59 +00:00
|
|
|
array_keys( $dropdownOptions[ $localisedGroup ] )
|
2021-03-04 11:24:20 +00:00
|
|
|
);
|
2024-03-09 14:44:59 +00:00
|
|
|
$dropdownOptions[ $localisedGroup ] = array_combine(
|
2021-03-04 11:24:20 +00:00
|
|
|
$newKeys,
|
2024-03-09 14:44:59 +00:00
|
|
|
$dropdownOptions[ $localisedGroup ]
|
2021-03-04 11:24:20 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-05-04 08:14:01 +00:00
|
|
|
$dropdownList = Html::listDropdownOptionsOoui( $dropdownOptions );
|
2021-03-04 11:24:20 +00:00
|
|
|
return new DropdownInputWidget( [
|
|
|
|
'name' => 'wpFilterBuilder',
|
|
|
|
'inputId' => 'wpFilterBuilder',
|
2024-03-09 14:44:59 +00:00
|
|
|
'options' => $dropdownList
|
2021-03-04 11:24:20 +00:00
|
|
|
] );
|
2020-11-24 12:16:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-03-04 11:24:20 +00:00
|
|
|
* Get an additional widget that "controls" the editor, and is placed next to it
|
|
|
|
* Precondition: the user has full rights.
|
2020-11-24 12:16:41 +00:00
|
|
|
*
|
2021-03-04 11:24:20 +00:00
|
|
|
* @return Widget
|
2020-11-24 12:16:41 +00:00
|
|
|
*/
|
2021-07-21 18:51:12 +00:00
|
|
|
protected function getEditorControls(): Widget {
|
2021-03-04 11:24:20 +00:00
|
|
|
return new ButtonWidget(
|
|
|
|
[
|
|
|
|
'label' => $this->localizer->msg( 'abusefilter-edit-check' )->text(),
|
|
|
|
'id' => 'mw-abusefilter-syntaxcheck'
|
|
|
|
]
|
|
|
|
);
|
2020-11-24 12:16:41 +00:00
|
|
|
}
|
|
|
|
|
2021-03-04 11:24:20 +00:00
|
|
|
/**
|
|
|
|
* Generate the HTML for the actual edit box
|
|
|
|
*
|
|
|
|
* @param string $rules
|
|
|
|
* @param bool $isUserAllowed
|
|
|
|
* @param bool $externalForm
|
|
|
|
* @return string
|
|
|
|
*/
|
2021-07-21 18:51:12 +00:00
|
|
|
abstract protected function getEditBox( string $rules, bool $isUserAllowed, bool $externalForm ): string;
|
2021-03-04 11:24:20 +00:00
|
|
|
|
2020-11-24 12:16:41 +00:00
|
|
|
}
|