Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialFindComment
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 11
380
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getFormFields
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 getSubpageField
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDisplayFormat
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 requiresPost
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getShowAlways
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 alterForm
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 onSubmit
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 onSuccess
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
42
 displayItems
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
20
 getDescription
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Extension\DiscussionTools;
4
5use MediaWiki\Html\Html;
6use MediaWiki\HTMLForm\HTMLForm;
7use MediaWiki\SpecialPage\FormSpecialPage;
8use MediaWiki\SpecialPage\SpecialPage;
9
10class SpecialFindComment extends FormSpecialPage {
11
12    private const LIST_LIMIT = 50;
13
14    private ThreadItemStore $threadItemStore;
15    private ThreadItemFormatter $threadItemFormatter;
16
17    public function __construct(
18        ThreadItemStore $threadItemStore,
19        ThreadItemFormatter $threadItemFormatter
20    ) {
21        parent::__construct( 'FindComment' );
22        $this->threadItemStore = $threadItemStore;
23        $this->threadItemFormatter = $threadItemFormatter;
24    }
25
26    /**
27     * @inheritDoc
28     */
29    protected function getFormFields() {
30        return [
31            'idorname' => [
32                'label-message' => 'discussiontools-findcomment-label-idorname',
33                'name' => 'idorname',
34                'type' => 'text',
35                'required' => true,
36            ],
37        ];
38    }
39
40    /**
41     * @inheritDoc
42     */
43    protected function getSubpageField() {
44        return 'idorname';
45    }
46
47    /**
48     * @inheritDoc
49     */
50    protected function getDisplayFormat() {
51        return 'ooui';
52    }
53
54    /**
55     * @inheritDoc
56     */
57    public function requiresPost() {
58        return false;
59    }
60
61    /**
62     * @inheritDoc
63     */
64    protected function getShowAlways() {
65        return true;
66    }
67
68    /**
69     * @inheritDoc
70     */
71    protected function alterForm( HTMLForm $form ) {
72        $form->setWrapperLegend( true );
73        $form->setSubmitTextMsg( 'discussiontools-findcomment-label-search' );
74    }
75
76    private string $idOrName;
77
78    /**
79     * @inheritDoc
80     */
81    public function onSubmit( array $data ) {
82        // They are correctly written with underscores, but allow spaces too for consistency with
83        // the behavior of internal wiki links.
84        $this->idOrName = str_replace( ' ', '_', $data['idorname'] );
85        return true;
86    }
87
88    /**
89     * @inheritDoc
90     */
91    public function onSuccess() {
92        $out = $this->getOutput();
93        $results = false;
94
95        if ( $this->idOrName ) {
96            $byId = $this->threadItemStore->findNewestRevisionsById( $this->idOrName, static::LIST_LIMIT + 1 );
97            if ( $byId ) {
98                $this->displayItems( $byId, 'discussiontools-findcomment-results-id' );
99                $results = true;
100            }
101
102            $byName = $this->threadItemStore->findNewestRevisionsByName( $this->idOrName, static::LIST_LIMIT + 1 );
103            if ( $byName ) {
104                $this->displayItems( $byName, 'discussiontools-findcomment-results-name' );
105                $results = true;
106            }
107        }
108
109        if ( $results ) {
110            // (T389741) Comment IDs/names may use characters that are not valid in page titles, like '<'.
111            // Omit the message with the wikilink to Special:GoToComment/… if the link would be invalid.
112            // They can only be linked to using external links to Special:FindComment?idorname=…
113            // or wikilinks to the target page with a fragment identifier, for example Talk:Foo#….
114            // It's a pity we haven't realized this before deciding on this linking scheme. Oops.
115            $specialPageTitle = SpecialPage::getSafeTitleFor( 'GoToComment', $this->idOrName );
116            if ( $specialPageTitle !== null ) {
117                $out->addHTML(
118                    $this->msg( 'discussiontools-findcomment-gotocomment', $this->idOrName )->parseAsBlock() );
119            }
120        } else {
121            $out->addHTML(
122                $this->msg( 'discussiontools-findcomment-noresults' )->parseAsBlock() );
123        }
124    }
125
126    private function displayItems( array $threadItems, string $msgKey ) {
127        $out = $this->getOutput();
128
129        $list = [];
130        foreach ( $threadItems as $item ) {
131            if ( count( $list ) === static::LIST_LIMIT ) {
132                break;
133            }
134            $line = $this->threadItemFormatter->formatLine( $item, $this );
135            $list[] = Html::rawElement( 'li', [], $line );
136        }
137
138        $out->addHTML( $this->msg( $msgKey, count( $list ) )->parseAsBlock() );
139        $out->addHTML( Html::rawElement( 'ul', [], implode( '', $list ) ) );
140        if ( count( $threadItems ) > static::LIST_LIMIT ) {
141            $out->addHTML( $this->msg( 'morenotlisted' )->parseAsBlock() );
142        }
143    }
144
145    /**
146     * @inheritDoc
147     */
148    public function getDescription() {
149        return $this->msg( 'discussiontools-findcomment-title' );
150    }
151}