Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 83
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialRestSandbox
0.00% covered (danger)
0.00%
0 / 83
0.00% covered (danger)
0.00%
0 / 7
272
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
 getApiSpecs
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isListed
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSpecUrl
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
30
 execute
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 1
12
 showForm
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 1
20
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\Specials;
22
23use MediaWiki\Html\Html;
24use MediaWiki\HTMLForm\HTMLForm;
25use MediaWiki\MainConfigNames;
26use MediaWiki\SpecialPage\SpecialPage;
27use MediaWiki\Utils\UrlUtils;
28
29/**
30 * A special page showing a Swagger UI for exploring REST APIs.
31 *
32 * @ingroup SpecialPage
33 * @since 1.43
34 */
35class SpecialRestSandbox extends SpecialPage {
36
37    private UrlUtils $urlUtils;
38
39    public function __construct( UrlUtils $urlUtils ) {
40        parent::__construct( 'RestSandbox' );
41
42        $this->urlUtils = $urlUtils;
43    }
44
45    /**
46     * Returns the available choices for APIs to explore.
47     *
48     * @see MainConfigSchema::RestSandboxSpecs for the structure of the array
49     *
50     * @return array[]
51     */
52    private function getApiSpecs(): array {
53        return $this->getConfig()->get( MainConfigNames::RestSandboxSpecs );
54    }
55
56    public function isListed() {
57        // Hide the special pages if there are no APIs to explore.
58        return $this->getApiSpecs() !== [];
59    }
60
61    protected function getGroupName() {
62        return 'wiki';
63    }
64
65    private function getSpecUrl( ?string $apiId ): ?string {
66        $apiSpecs = $this->getApiSpecs();
67
68        if ( $apiId !== null && $apiId !== '' ) {
69            $spec = $apiSpecs[$apiId] ?? null;
70        } else {
71            $spec = reset( $apiSpecs ) ?: null;
72        }
73
74        if ( !$spec ) {
75            return null;
76        }
77
78        return $this->urlUtils->expand( $spec['url'] );
79    }
80
81    public function execute( $sub ) {
82        $this->setHeaders();
83        $out = $this->getOutput();
84        $this->addHelpLink( 'Help:RestSandbox' );
85
86        $apiId = $this->getRequest()->getText( 'api', $sub ?? '' );
87        $specUrl = $this->getSpecUrl( $apiId );
88
89        $apiSpecs = $this->getApiSpecs();
90
91        $out->addJsConfigVars( [
92            'specUrl' => $specUrl
93        ] );
94
95        $out->addModuleStyles( [
96            'mediawiki.special',
97            'mediawiki.hlist',
98            'mediawiki.special.restsandbox.styles'
99        ] );
100
101        if ( !$apiSpecs ) {
102            $out->addHTML( Html::errorBox(
103                $out->msg( 'restsandbox-no-specs-configured' )
104            ) );
105            return;
106        }
107
108        $this->showForm( $apiSpecs );
109
110        if ( !$specUrl ) {
111            $out->addHTML( Html::errorBox(
112                $out->msg( 'restsandbox-no-such-api' )->params( $apiId )
113            ) );
114            return;
115        }
116
117        $out->addModules( [
118            'mediawiki.special.restsandbox'
119        ] );
120
121        $out->addHTML( Html::openElement( 'div', [ 'id' => 'mw-restsandbox' ] ) );
122
123        // Hidden when JS is available
124        $out->wrapWikiMsg(
125            Html::element(
126                'div',
127                [ 'class' => [ 'mw-restsandbox-client-nojs', 'error', ], ],
128                "\n$1\n"
129            ),
130            'restsandbox-jsonly'
131        );
132
133        // To be replaced by Swagger UI.
134        $out->addElement( 'div', [ 'id' => 'mw-restsandbox-swagger-ui' ] );
135
136        $out->addHTML( Html::closeElement( 'div' ) ); // #mw-restsandbox
137    }
138
139    private function showForm( array $apiSpecs ) {
140        $apis = [];
141
142        foreach ( $apiSpecs as $key => $spec ) {
143            if ( isset( $spec['msg'] ) ) {
144                $text = $this->msg( $spec['msg'] )->plain();
145            } elseif ( isset( $spec['name'] ) ) {
146                $text = $spec['name'];
147            } else {
148                $text = $key;
149            }
150
151            $apis[$text] = $key;
152        }
153
154        $formDescriptor = [
155            'intro' => [
156                'type' => 'info',
157                'raw' => true,
158                'default' => $this->msg( 'restsandbox-text' )->parseAsBlock()
159            ],
160            'api' => [
161                'type' => 'select',
162                'name' => 'api',
163                'label-message' => 'restsandbox-select-api',
164                'options' => $apis
165            ],
166            'title' => [
167                'type' => 'hidden',
168                'name' => 'title',
169                'default' => $this->getPageTitle()->getPrefixedDBkey()
170            ],
171        ];
172
173        $action = $this->getPageTitle()->getLocalURL( [ 'action' => 'submit' ] );
174
175        $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() );
176        $htmlForm->setAction( $action );
177        $htmlForm->setMethod( 'GET' );
178        $htmlForm->setId( 'mw-restsandbox-form' );
179        $htmlForm->prepareForm()->displayForm( false );
180    }
181}