Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
8.62% covered (danger)
8.62%
5 / 58
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
EditBoxBuilder
8.62% covered (danger)
8.62%
5 / 58
25.00% covered (danger)
25.00%
1 / 4
70.81
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 buildEditBox
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
30
 getSuggestionsDropdown
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
6
 getEditorControls
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getEditBox
n/a
0 / 0
n/a
0 / 0
0
1<?php
2
3namespace MediaWiki\Extension\AbuseFilter\EditBox;
4
5use MediaWiki\Extension\AbuseFilter\AbuseFilterPermissionManager;
6use MediaWiki\Extension\AbuseFilter\KeywordsManager;
7use MediaWiki\Output\OutputPage;
8use MediaWiki\Permissions\Authority;
9use MessageLocalizer;
10use OOUI\ButtonWidget;
11use OOUI\DropdownInputWidget;
12use OOUI\FieldLayout;
13use OOUI\FieldsetLayout;
14use OOUI\Widget;
15use Xml;
16
17/**
18 * Base class for classes responsible for building filter edit boxes
19 */
20abstract class EditBoxBuilder {
21    /** @var AbuseFilterPermissionManager */
22    protected $afPermManager;
23
24    /** @var KeywordsManager */
25    protected $keywordsManager;
26
27    /** @var MessageLocalizer */
28    protected $localizer;
29
30    /** @var Authority */
31    protected $authority;
32
33    /** @var OutputPage */
34    protected $output;
35
36    /**
37     * @param AbuseFilterPermissionManager $afPermManager
38     * @param KeywordsManager $keywordsManager
39     * @param MessageLocalizer $messageLocalizer
40     * @param Authority $authority
41     * @param OutputPage $output
42     */
43    public function __construct(
44        AbuseFilterPermissionManager $afPermManager,
45        KeywordsManager $keywordsManager,
46        MessageLocalizer $messageLocalizer,
47        Authority $authority,
48        OutputPage $output
49    ) {
50        $this->afPermManager = $afPermManager;
51        $this->keywordsManager = $keywordsManager;
52        $this->localizer = $messageLocalizer;
53        $this->authority = $authority;
54        $this->output = $output;
55    }
56
57    /**
58     * @param string $rules
59     * @param bool $addResultDiv
60     * @param bool $externalForm
61     * @param bool $needsModifyRights
62     * @param-taint $rules none
63     * @return string
64     */
65    public function buildEditBox(
66        string $rules,
67        bool $addResultDiv = true,
68        bool $externalForm = false,
69        bool $needsModifyRights = true
70    ): string {
71        $this->output->addModules( 'ext.abuseFilter.edit' );
72        $this->output->enableOOUI();
73
74        $isUserAllowed = $needsModifyRights ?
75            $this->afPermManager->canEdit( $this->authority ) :
76            $this->afPermManager->canUseTestTools( $this->authority );
77        if ( !$isUserAllowed ) {
78            $addResultDiv = false;
79        }
80
81        $output = $this->getEditBox( $rules, $isUserAllowed, $externalForm );
82
83        if ( $isUserAllowed ) {
84            $dropdown = $this->getSuggestionsDropdown();
85
86            $formElements = [
87                new FieldLayout( $dropdown ),
88                new FieldLayout( $this->getEditorControls() )
89            ];
90
91            $fieldSet = new FieldsetLayout( [
92                'items' => $formElements,
93                'classes' => [ 'mw-abusefilter-edit-buttons', 'mw-abusefilter-javascript-tools' ]
94            ] );
95
96            $output .= $fieldSet;
97        }
98
99        if ( $addResultDiv ) {
100            $output .= Xml::element(
101                'div',
102                [ 'id' => 'mw-abusefilter-syntaxresult', 'style' => 'display: none;' ],
103                '&#160;'
104            );
105        }
106
107        return $output;
108    }
109
110    /**
111     * @return DropdownInputWidget
112     */
113    private function getSuggestionsDropdown(): DropdownInputWidget {
114        $rawDropdown = $this->keywordsManager->getBuilderValues();
115
116        // The array needs to be rearranged to be understood by OOUI. It comes with the format
117        // [ group-msg-key => [ text-to-add => text-msg-key ] ] and we need it as
118        // [ group-msg => [ text-msg => text-to-add ] ]
119        // Also, the 'other' element must be the first one.
120        $dropdownOptions = [ $this->localizer->msg( 'abusefilter-edit-builder-select' )->text() => 'other' ];
121        foreach ( $rawDropdown as $group => $values ) {
122            // Give grep a chance to find the usages:
123            // abusefilter-edit-builder-group-op-arithmetic, abusefilter-edit-builder-group-op-comparison,
124            // abusefilter-edit-builder-group-op-bool, abusefilter-edit-builder-group-misc,
125            // abusefilter-edit-builder-group-funcs, abusefilter-edit-builder-group-vars
126            $localisedGroup = $this->localizer->msg( "abusefilter-edit-builder-group-$group" )->text();
127            $dropdownOptions[ $localisedGroup ] = array_flip( $values );
128            $newKeys = array_map(
129                function ( $key ) use ( $group ) {
130                    return $this->localizer->msg( "abusefilter-edit-builder-$group-$key" )->text();
131                },
132                array_keys( $dropdownOptions[ $localisedGroup ] )
133            );
134            $dropdownOptions[ $localisedGroup ] = array_combine(
135                $newKeys,
136                $dropdownOptions[ $localisedGroup ]
137            );
138        }
139
140        $dropdownList = Xml::listDropdownOptionsOoui( $dropdownOptions );
141        return new DropdownInputWidget( [
142            'name' => 'wpFilterBuilder',
143            'inputId' => 'wpFilterBuilder',
144            'options' => $dropdownList
145        ] );
146    }
147
148    /**
149     * Get an additional widget that "controls" the editor, and is placed next to it
150     * Precondition: the user has full rights.
151     *
152     * @return Widget
153     */
154    protected function getEditorControls(): Widget {
155        return new ButtonWidget(
156            [
157                'label' => $this->localizer->msg( 'abusefilter-edit-check' )->text(),
158                'id' => 'mw-abusefilter-syntaxcheck'
159            ]
160        );
161    }
162
163    /**
164     * Generate the HTML for the actual edit box
165     *
166     * @param string $rules
167     * @param bool $isUserAllowed
168     * @param bool $externalForm
169     * @return string
170     */
171    abstract protected function getEditBox( string $rules, bool $isUserAllowed, bool $externalForm ): string;
172
173}