Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
67.69% covered (warning)
67.69%
44 / 65
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialSimilarEditors
67.69% covered (warning)
67.69%
44 / 65
75.00% covered (warning)
75.00%
3 / 4
22.59
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 execute
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
1 / 1
5
 onSubmit
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 onSuccess
36.36% covered (danger)
36.36%
12 / 33
0.00% covered (danger)
0.00%
0 / 1
24.49
1<?php
2
3namespace MediaWiki\Extension\SimilarEditors;
4
5use MediaWiki\Html\Html;
6use MediaWiki\HTMLForm\HTMLForm;
7use MediaWiki\SpecialPage\SpecialPage;
8use MediaWiki\Status\Status;
9use OOUI\HtmlSnippet;
10use OOUI\MessageWidget;
11
12class SpecialSimilarEditors extends SpecialPage {
13
14    /** @var HTMLForm */
15    private $form;
16
17    public function __construct(
18        private readonly Client $similarEditorsClient,
19        private readonly ResultsFormatterFactory $resultsFormatterFactory,
20    ) {
21        parent::__construct( 'SimilarEditors', 'similareditors', true );
22    }
23
24    /**
25     * @inheritDoc
26     */
27    public function execute( $par ) {
28        $this->setHeaders();
29        $this->checkPermissions();
30        $this->outputHeader();
31        $this->addHelpLink( 'Help:Extension:SimilarEditors' );
32
33        $out = $this->getOutput();
34        $out->addModuleStyles( 'mediawiki.pager.styles' );
35        $out->addModuleStyles( 'ext.similarEditors.styles' );
36
37        // Ensure the correct survey is added, in case multiple are enabled
38        $out->addHTML( Html::element( 'div', [ 'id' => 'similareditors-survey-embed' ] ) );
39
40        $fields = [
41            'Target' => [
42                'type' => 'user',
43                'label-message' => 'similareditors-form-field-target-label',
44                'placeholder-message' => 'similareditors-form-field-target-placeholder',
45                // TODO: revert as part of T309675
46                'exists' => false,
47                'ipallowed' => true,
48                'required' => true,
49            ],
50        ];
51
52        $this->form = HTMLForm::factory( 'ooui', $fields, $this->getContext() );
53        $this->form
54            ->setMethod( 'post' )
55            ->setWrapperLegendMsg( 'similareditors-form-legend' )
56            ->setSubmitTextMsg( 'similareditors-form-submit' )
57            ->setSubmitCallback( [ $this, 'onSubmit' ] );
58
59        if ( $this->getRequest()->getVal( 'wpTarget' ) === null ) {
60            $this->form->prepareForm()
61                ->displayForm( false );
62        } else {
63            $status = $this->form->show();
64            if ( $status === true || ( $status instanceof Status && $status->isGood() ) ) {
65                $this->onSuccess();
66            }
67        }
68    }
69
70    /**
71     * Placeholder for the submit callback as required by HTMLForm
72     *
73     * @param array $formData
74     * @return bool
75     */
76    public function onSubmit( $formData ) {
77        return true;
78    }
79
80    /**
81     * Handle successful form submission.
82     *
83     * This includes handling errors from the Similarusers service.
84     */
85    public function onSuccess() {
86        $out = $this->getOutput();
87
88        $target = $this->getRequest()->getVal( 'wpTarget' );
89        $result = $this->similarEditorsClient->getSimilarEditors( $target );
90
91        if ( is_array( $result ) ) {
92            $this->form->displayForm( true );
93            $out->addModules( 'ext.similarEditors' );
94            if ( count( $result ) > 0 ) {
95                $resultsFormatter = $this->resultsFormatterFactory->createFormatter(
96                    $this->getLanguage()
97                );
98                $out->addHtml( $resultsFormatter->formatResults( $target, $result ) );
99            } else {
100                $out->addHtml( $this->msg( 'similareditors-no-results' ) );
101            }
102        } else {
103            switch ( $result ) {
104                // We encountered an error, but with no type or an unrecognized type.
105                // Display the default message instead of a customized message.
106                case 'database-refresh':
107                    $message = $this->msg( 'similareditors-error-database-refresh' );
108                    break;
109                case 'user-no-account':
110                    $message = $this->msg( 'similareditors-error-user-no-account', $target );
111                    break;
112                case 'user-bot':
113                    $message = $this->msg( 'similareditors-error-user-bot', $target );
114                    break;
115                case 'user-no-edits':
116                    $message = $this->msg( 'similareditors-error-user-no-edits', $target );
117                    break;
118                default:
119                    $message = 'similareditors-error-default';
120            }
121            $out->addHtml(
122                new MessageWidget( [
123                    'type' => 'error',
124                    'label' => new HtmlSnippet(
125                        $this->msg( $message )->parse() ),
126                ] )
127            );
128            $this->form->displayForm( false );
129        }
130    }
131}