Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
86.46% covered (warning)
86.46%
83 / 96
50.00% covered (danger)
50.00%
3 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
QueryAllCampaigns
86.46% covered (warning)
86.46%
83 / 96
50.00% covered (danger)
50.00%
3 / 6
17.72
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 execute
89.19% covered (warning)
89.19%
66 / 74
0.00% covered (danger)
0.00%
0 / 1
12.18
 getCacheMode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAllowedParams
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
1
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getHelpUrls
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Extension\MediaUploader\Api;
4
5use ApiBase;
6use ApiQuery;
7use ApiQueryBase;
8use ApiUsageException;
9use MediaWiki\Extension\MediaUploader\Campaign\CampaignRecord;
10use MediaWiki\Extension\MediaUploader\Campaign\CampaignStats;
11use MediaWiki\Extension\MediaUploader\Campaign\CampaignStore;
12use MediaWiki\Extension\MediaUploader\Campaign\Exception\BaseCampaignException;
13use MWException;
14use Wikimedia\ParamValidator\ParamValidator;
15use Wikimedia\ParamValidator\TypeDef\IntegerDef;
16
17/**
18 * Query module to enumerate all registered campaigns
19 *
20 * @ingroup API
21 */
22class QueryAllCampaigns extends ApiQueryBase {
23
24    /** @var CampaignStore */
25    private $campaignStore;
26
27    /** @var CampaignStats */
28    private $campaignStats;
29
30    /**
31     * @param ApiQuery $query
32     * @param string $moduleName
33     * @param CampaignStore $campaignStore
34     * @param CampaignStats $campaignStats
35     */
36    public function __construct(
37        ApiQuery $query,
38        string $moduleName,
39        CampaignStore $campaignStore,
40        CampaignStats $campaignStats
41    ) {
42        // Prefix: MediaUploader – Campaigns
43        parent::__construct( $query, $moduleName, 'muc' );
44
45        $this->campaignStore = $campaignStore;
46        $this->campaignStats = $campaignStats;
47    }
48
49    /**
50     * @throws ApiUsageException
51     * @throws MWException
52     */
53    public function execute() {
54        $params = $this->extractRequestParams();
55        $limit = $params['limit'];
56        $queryBuilder = $this->campaignStore->newSelectQueryBuilder()
57            ->orderByIdAsc()
58            ->option( 'LIMIT', $limit + 1 );
59
60        if ( $params['enabledonly'] ) {
61            $queryBuilder->whereEnabled( true );
62        }
63
64        if ( $params['continue'] !== null ) {
65            $from_id = (int)$params['continue'];
66            // Not SQL Injection, since we already force this to be an integer
67            $queryBuilder->where( "campaign_page_id >= $from_id" );
68        }
69
70        $result = $this->getResult();
71        $count = 0;
72        $recordsUnfiltered = $queryBuilder->fetchCampaignRecords(
73            CampaignStore::SELECT_TITLE
74        );
75
76        // First scan the retrieved records for validity
77        $records = [];
78        $basePath = [ 'query', $this->getModuleName() ];
79
80        foreach ( $recordsUnfiltered as $record ) {
81            /** @var CampaignRecord $record */
82            if ( ++$count > $limit ) {
83                // We have more results than $limit. Set continue
84                $this->setContinueEnumParameter(
85                    'continue',
86                    $record->getPageId() ?: 0
87                );
88                break;
89            }
90
91            try {
92                $record->assertValid(
93                    $record->getPage()->getDBkey(),
94                    CampaignStore::SELECT_TITLE
95                );
96            } catch ( BaseCampaignException $e ) {
97                $result->addValue(
98                    $basePath,
99                    $record->getPageId(),
100                    [
101                        'name' => $record->getPage()->getDBkey(),
102                        'enabled' => $record->isEnabled(),
103                        'error' => $e->getMessage(),
104                    ]
105                );
106                continue;
107            }
108            $records[] = $record;
109        }
110
111        // Fetch stats in batch
112        $stats = $this->campaignStats->getStatsForRecords( $records );
113
114        foreach ( $records as $record ) {
115            /** @var CampaignRecord $record */
116            $campaignPath = [ 'query', $this->getModuleName(), $record->getPageId() ];
117
118            $result->addValue(
119                $campaignPath,
120                'name',
121                $record->getPage()->getDBkey()
122            );
123            $result->addValue(
124                $campaignPath,
125                'enabled',
126                $record->isEnabled()
127            );
128
129            $statsRecord = $stats[$record->getPageId() ?: -1] ?? [];
130            if ( array_key_exists( 'trackingCategory', $statsRecord ) ) {
131                $result->addValue(
132                    $campaignPath,
133                    'trackingCategory',
134                    $statsRecord['trackingCategory']
135                );
136            } else {
137                // The stats cannot be computed without a tracking category
138                continue;
139            }
140
141            if ( array_key_exists( 'uploadedMediaCount', $statsRecord ) ) {
142                $result->addValue(
143                    $campaignPath,
144                    'totalUploads',
145                    $statsRecord['uploadedMediaCount']
146                );
147            }
148            if ( array_key_exists( 'contributorsCount', $statsRecord ) ) {
149                $result->addValue(
150                    $campaignPath,
151                    'totalContributors',
152                    $statsRecord['contributorsCount']
153                );
154            }
155        }
156        $result->addIndexedTagName( [ 'query', $this->getModuleName() ], 'campaign' );
157    }
158
159    public function getCacheMode( $params ) {
160        return 'public';
161    }
162
163    public function getAllowedParams() {
164        return [
165            'enabledonly' => false,
166            'limit' => [
167                ParamValidator::PARAM_DEFAULT => 50,
168                ParamValidator::PARAM_TYPE => 'limit',
169                IntegerDef::PARAM_MIN => 1,
170                IntegerDef::PARAM_MAX => ApiBase::LIMIT_SML1,
171                IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_SML2,
172            ],
173            'continue' => [
174                ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
175            ],
176        ];
177    }
178
179    /**
180     * @inheritDoc
181     */
182    protected function getExamplesMessages() {
183        return [
184            'action=query&list=allcampaigns&mucenabledonly='
185                => 'apihelp-query+allcampaigns-example-1',
186        ];
187    }
188
189    public function getHelpUrls() {
190        // TODO: point to a subpage with API docs when it gets created
191        return 'https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:MediaUploader';
192    }
193}