Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 125
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiQueryGadgets
0.00% covered (danger)
0.00%
0 / 125
0.00% covered (danger)
0.00%
0 / 9
1122
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
56
 getList
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
56
 applyList
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
30
 isNeeded
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
42
 fakeMetadata
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
2
 setIndexedTagNameForMetadata
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
20
 getAllowedParams
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
2
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21namespace MediaWiki\Extension\Gadgets\Api;
22
23use ApiBase;
24use ApiQuery;
25use ApiQueryBase;
26use ApiResult;
27use MediaWiki\Extension\Gadgets\Gadget;
28use MediaWiki\Extension\Gadgets\GadgetRepo;
29use Wikimedia\ParamValidator\ParamValidator;
30
31class ApiQueryGadgets extends ApiQueryBase {
32    private array $props;
33
34    /**
35     * @var array|bool
36     */
37    private $categories;
38
39    /**
40     * @var array|bool
41     */
42    private $neededIds;
43
44    private bool $listAllowed;
45
46    private bool $listEnabled;
47
48    private GadgetRepo $gadgetRepo;
49
50    public function __construct( ApiQuery $queryModule, $moduleName, GadgetRepo $gadgetRepo ) {
51        parent::__construct( $queryModule, $moduleName, 'ga' );
52        $this->gadgetRepo = $gadgetRepo;
53    }
54
55    public function execute() {
56        $params = $this->extractRequestParams();
57        $this->props = array_flip( $params['prop'] );
58        $this->categories = isset( $params['categories'] )
59            ? array_flip( $params['categories'] )
60            : false;
61        $this->neededIds = isset( $params['ids'] )
62            ? array_flip( $params['ids'] )
63            : false;
64        $this->listAllowed = isset( $params['allowedonly'] ) && $params['allowedonly'];
65        $this->listEnabled = isset( $params['enabledonly'] ) && $params['enabledonly'];
66
67        $this->getMain()->setCacheMode( $this->listAllowed || $this->listEnabled
68            ? 'anon-public-user-private' : 'public' );
69
70        $this->applyList( $this->getList() );
71    }
72
73    private function getList(): array {
74        $gadgets = $this->gadgetRepo->getStructuredList();
75
76        if ( !$gadgets ) {
77            return [];
78        }
79
80        $result = [];
81        foreach ( $gadgets as $category => $list ) {
82            if ( $this->categories && !isset( $this->categories[$category] ) ) {
83                continue;
84            }
85
86            foreach ( $list as $g ) {
87                if ( $this->isNeeded( $g ) ) {
88                    $result[] = $g;
89                }
90            }
91        }
92        return $result;
93    }
94
95    private function applyList( array $gadgets ): void {
96        $data = [];
97        $result = $this->getResult();
98
99        /**
100         * @var $g Gadget
101         */
102        foreach ( $gadgets as $g ) {
103            $row = [];
104            if ( isset( $this->props['id'] ) ) {
105                $row['id'] = $g->getName();
106            }
107
108            if ( isset( $this->props['metadata'] ) ) {
109                $row['metadata'] = $this->fakeMetadata( $g );
110                $this->setIndexedTagNameForMetadata( $row['metadata'] );
111            }
112
113            if ( isset( $this->props['desc'] ) ) {
114                $row['desc'] = $g->getDescription();
115            }
116
117            $data[] = $row;
118        }
119
120        ApiResult::setIndexedTagName( $data, 'gadget' );
121        $result->addValue( 'query', $this->getModuleName(), $data );
122    }
123
124    private function isNeeded( Gadget $gadget ): bool {
125        $user = $this->getUser();
126
127        return ( $this->neededIds === false || isset( $this->neededIds[$gadget->getName()] ) )
128            && ( !$this->listAllowed || $gadget->isAllowed( $user ) )
129            && ( !$this->listEnabled || $gadget->isEnabled( $user ) );
130    }
131
132    private function fakeMetadata( Gadget $g ): array {
133        return [
134            'settings' => [
135                'actions' => $g->getRequiredActions(),
136                'categories' => $g->getRequiredCategories(),
137                'category' => $g->getCategory(),
138                'contentModels' => $g->getRequiredContentModels(),
139                'default' => $g->isOnByDefault(),
140                'hidden' => $g->isHidden(),
141                'legacyscripts' => (bool)$g->getLegacyScripts(),
142                'namespaces' => $g->getRequiredNamespaces(),
143                'package' => $g->isPackaged(),
144                'requiresES6' => $g->requiresES6(),
145                'rights' => $g->getRequiredRights(),
146                'shared' => false,
147                'skins' => $g->getRequiredSkins(),
148                'supportsUrlLoad' => $g->supportsUrlLoad(),
149            ],
150            'module' => [
151                'datas' => $g->getJSONs(),
152                'dependencies' => $g->getDependencies(),
153                'messages' => $g->getMessages(),
154                'peers' => $g->getPeers(),
155                'scripts' => $g->getScripts(),
156                'styles' => $g->getStyles(),
157            ]
158        ];
159    }
160
161    private function setIndexedTagNameForMetadata( array &$metadata ): void {
162        static $tagNames = [
163            'actions' => 'action',
164            'categories' => 'category',
165            'contentModels' => 'contentModel',
166            'datas' => 'data',
167            'dependencies' => 'dependency',
168            'messages' => 'message',
169            'namespaces' => 'namespace',
170            'peers' => 'peer',
171            'rights' => 'right',
172            'scripts' => 'script',
173            'skins' => 'skin',
174            'styles' => 'style',
175        ];
176
177        foreach ( $metadata as $data ) {
178            foreach ( $data as $key => $value ) {
179                if ( is_array( $value ) ) {
180                    $tag = $tagNames[$key] ?? $key;
181                    ApiResult::setIndexedTagName( $value, $tag );
182                }
183            }
184        }
185    }
186
187    public function getAllowedParams() {
188        return [
189            'prop' => [
190                ParamValidator::PARAM_DEFAULT => 'id|metadata',
191                ParamValidator::PARAM_ISMULTI => true,
192                ParamValidator::PARAM_TYPE => [
193                    'id',
194                    'metadata',
195                    'desc',
196                ],
197                ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
198            ],
199            'categories' => [
200                ParamValidator::PARAM_ISMULTI => true,
201                ParamValidator::PARAM_TYPE => 'string',
202            ],
203            'ids' => [
204                ParamValidator::PARAM_TYPE => 'string',
205                ParamValidator::PARAM_ISMULTI => true,
206            ],
207            'allowedonly' => false,
208            'enabledonly' => false,
209        ];
210    }
211
212    /**
213     * @see ApiBase::getExamplesMessages()
214     * @return array
215     */
216    protected function getExamplesMessages() {
217        $params = $this->getAllowedParams();
218        $allProps = implode( '|', $params['prop'][ParamValidator::PARAM_TYPE] );
219        return [
220            'action=query&list=gadgets&gaprop=id|desc'
221                => 'apihelp-query+gadgets-example-1',
222            "action=query&list=gadgets&gaprop=$allProps"
223                => 'apihelp-query+gadgets-example-2',
224            'action=query&list=gadgets&gacategories=foo'
225                => 'apihelp-query+gadgets-example-3',
226            'action=query&list=gadgets&gaids=foo|bar&gaprop=id|desc|metadata'
227                => 'apihelp-query+gadgets-example-4',
228            'action=query&list=gadgets&gaenabledonly'
229                => 'apihelp-query+gadgets-example-5',
230        ];
231    }
232}