Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiDiscussionToolsFindComment
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 6
420
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
 execute
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 1
182
 getValue
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 getAllowedParams
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
2
 needsToken
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isWriteMode
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 ApiBase;
6use ApiMain;
7use ApiUsageException;
8use MediaWiki\Extension\DiscussionTools\ThreadItem\DatabaseThreadItem;
9use MediaWiki\Title\Title;
10use MediaWiki\Title\TitleFormatter;
11use Wikimedia\ParamValidator\ParamValidator;
12
13class ApiDiscussionToolsFindComment extends ApiBase {
14
15    private ThreadItemStore $threadItemStore;
16    private TitleFormatter $titleFormatter;
17
18    public function __construct(
19        ApiMain $main,
20        string $name,
21        ThreadItemStore $threadItemStore,
22        TitleFormatter $titleFormatter
23    ) {
24        parent::__construct( $main, $name );
25        $this->threadItemStore = $threadItemStore;
26        $this->titleFormatter = $titleFormatter;
27    }
28
29    /**
30     * @inheritDoc
31     * @throws ApiUsageException
32     */
33    public function execute() {
34        $params = $this->extractRequestParams();
35
36        $values = [];
37
38        $this->requireAtLeastOneParameter( $params, 'idorname', 'heading', 'page' );
39
40        if ( $params['idorname'] ) {
41            $idOrName = $params['idorname'];
42
43            $byId = $this->threadItemStore->findNewestRevisionsById( $idOrName );
44            foreach ( $byId as $item ) {
45                $values[] = $this->getValue( $item, 'id' );
46            }
47
48            $byName = $this->threadItemStore->findNewestRevisionsByName( $idOrName );
49            foreach ( $byName as $item ) {
50                $values[] = $this->getValue( $item, 'name' );
51            }
52        } else {
53            $this->requireAtLeastOneParameter( $params, 'heading' );
54            $this->requireAtLeastOneParameter( $params, 'page' );
55
56            $heading = $params['heading'];
57            $page = $params['page'];
58
59            $title = Title::newFromText( $page );
60            if ( $title ) {
61                $articleId = $title->getArticleId();
62
63                if ( $articleId ) {
64                    $byHeading = $this->threadItemStore->findNewestRevisionsByHeading(
65                        $heading, $articleId, $title->getTitleValue()
66                    );
67                    foreach ( $byHeading as $item ) {
68                        $values[] = $this->getValue( $item, 'heading' );
69                    }
70                }
71            }
72        }
73
74        $redirects = 0;
75        foreach ( $values as $value ) {
76            if ( $value['couldredirect'] ) {
77                $redirects++;
78                if ( $redirects > 1 ) {
79                    break;
80                }
81            }
82        }
83        foreach ( $values as $value ) {
84            if ( $redirects === 1 && $value['couldredirect'] ) {
85                $value['shouldredirect'] = true;
86            }
87            $this->getResult()->addValue( $this->getModuleName(), null, $value );
88        }
89    }
90
91    /**
92     * Get a value to add to the results
93     *
94     * @param DatabaseThreadItem $item Thread item
95     * @param string $matchedBy How the thread item was matched (id, name or heading)
96     * @return array
97     */
98    private function getValue( DatabaseThreadItem $item, string $matchedBy ): array {
99        $title = Title::castFromPageReference( $item->getPage() );
100
101        return [
102            'id' => $item->getId(),
103            'name' => $item->getName(),
104            'title' => $this->titleFormatter->getPrefixedText( $item->getPage() ),
105            'oldid' => !$item->getRevision()->isCurrent() ? $item->getRevision()->getId() : null,
106            'matchedby' => $matchedBy,
107            // Could this be an automatic redirect? Will be converted to 'shouldredirect'
108            // if there is only one of these in the result set.
109            // Matches logic in Special:GoToComment
110            'couldredirect' => $item->getRevision()->isCurrent() && !is_string( $item->getTranscludedFrom() )
111        ];
112    }
113
114    /**
115     * @inheritDoc
116     */
117    public function getAllowedParams() {
118        return [
119            'idorname' => [
120                ParamValidator::PARAM_TYPE => 'string',
121            ],
122            'heading' => [
123                ParamValidator::PARAM_TYPE => 'string',
124            ],
125            'page' => [
126                ParamValidator::PARAM_TYPE => 'string',
127            ],
128        ];
129    }
130
131    /**
132     * @inheritDoc
133     */
134    public function needsToken() {
135        return false;
136    }
137
138    /**
139     * @inheritDoc
140     */
141    public function isWriteMode() {
142        return false;
143    }
144}