Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
36.00% covered (danger)
36.00%
27 / 75
62.50% covered (warning)
62.50%
5 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
GadgetDefinitionContentHandler
36.00% covered (danger)
36.00%
27 / 75
62.50% covered (warning)
62.50%
5 / 8
188.84
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 canBeUsedOn
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getContentClass
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 makeEmptyContent
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getEmptyDefinition
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 getDefaultMetadata
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
2
 fillParserOutput
37.50% covered (danger)
37.50%
12 / 32
0.00% covered (danger)
0.00%
0 / 1
87.56
 makeLink
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
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\Content;
22
23use Content;
24use FormatJson;
25use JsonContentHandler;
26use MediaWiki\Content\Renderer\ContentParseParams;
27use MediaWiki\Extension\Gadgets\GadgetRepo;
28use MediaWiki\Extension\Gadgets\MediaWikiGadgetsJsonRepo;
29use MediaWiki\Linker\Linker;
30use MediaWiki\Parser\ParserOutput;
31use MediaWiki\Title\Title;
32
33class GadgetDefinitionContentHandler extends JsonContentHandler {
34    private GadgetRepo $gadgetRepo;
35
36    public function __construct( string $modelId, GadgetRepo $gadgetRepo ) {
37        parent::__construct( $modelId );
38        $this->gadgetRepo = $gadgetRepo;
39    }
40
41    /**
42     * @param Title $title
43     * @return bool
44     */
45    public function canBeUsedOn( Title $title ) {
46        return MediaWikiGadgetsJsonRepo::isGadgetDefinitionTitle( $title );
47    }
48
49    /** @inheritDoc */
50    protected function getContentClass() {
51        return GadgetDefinitionContent::class;
52    }
53
54    public function makeEmptyContent() {
55        $class = $this->getContentClass();
56        return new $class( FormatJson::encode( $this->getEmptyDefinition(), "\t" ) );
57    }
58
59    public function getEmptyDefinition() {
60        return [
61            'settings' => [
62                'category' => '',
63            ],
64            'module' => [
65                'pages' => [],
66                'dependencies' => [],
67            ]
68        ];
69    }
70
71    public function getDefaultMetadata() {
72        return [
73            'settings' => [
74                'rights' => [],
75                'default' => false,
76                'package' => false,
77                'requiresES6' => false,
78                'hidden' => false,
79                'skins' => [],
80                'actions' => [],
81                'namespaces' => [],
82                'categories' => [],
83                'contentModels' => [],
84                'category' => '',
85                'supportsUrlLoad' => false,
86            ],
87            'module' => [
88                'pages' => [],
89                'peers' => [],
90                'dependencies' => [],
91                'messages' => [],
92                'type' => '',
93            ],
94        ];
95    }
96
97    /**
98     * @inheritDoc
99     */
100    protected function fillParserOutput(
101        Content $content,
102        ContentParseParams $cpoParams,
103        ParserOutput &$parserOutput
104    ) {
105        '@phan-var GadgetDefinitionContent $content';
106        // Create a deep clone. FIXME: unserialize(serialize()) is hacky.
107        $data = unserialize( serialize( $content->getData()->getValue() ) );
108        if ( $data !== null ) {
109            if ( isset( $data->module->pages ) ) {
110                foreach ( $data->module->pages as &$page ) {
111                    $title = Title::makeTitleSafe( NS_MEDIAWIKI, "Gadget-$page" );
112                    $this->makeLink( $parserOutput, $page, $title );
113                }
114            }
115            if ( isset( $data->module->dependencies ) ) {
116                foreach ( $data->module->dependencies as &$dep ) {
117                    if ( str_starts_with( $dep, 'ext.gadget.' ) ) {
118                        $gadgetId = explode( 'ext.gadget.', $dep )[ 1 ];
119                        $title = $this->gadgetRepo->getGadgetDefinitionTitle( $gadgetId );
120                        if ( $title ) {
121                            $this->makeLink( $parserOutput, $dep, $title );
122                        }
123                    }
124                }
125            }
126            if ( isset( $data->module->peers ) ) {
127                foreach ( $data->module->peers as &$peer ) {
128                    $title = $this->gadgetRepo->getGadgetDefinitionTitle( $peer );
129                    if ( $title ) {
130                        $this->makeLink( $parserOutput, $peer, $title );
131                    }
132                }
133            }
134            if ( isset( $data->module->messages ) ) {
135                foreach ( $data->module->messages as &$msg ) {
136                    $title = Title::makeTitleSafe( NS_MEDIAWIKI, $msg );
137                    $this->makeLink( $parserOutput, $msg, $title );
138                }
139            }
140            if ( isset( $data->settings->category ) && $data->settings->category ) {
141                $this->makeLink(
142                    $parserOutput,
143                    $data->settings->category,
144                    Title::makeTitleSafe( NS_MEDIAWIKI, "gadget-section-" . $data->settings->category )
145                );
146            }
147        }
148
149        if ( !$cpoParams->getGenerateHtml() || !$content->isValid() ) {
150            $parserOutput->setText( '' );
151        } else {
152            $parserOutput->setText( $content->rootValueTable( $data ) );
153            $parserOutput->addModuleStyles( [ 'mediawiki.content.json' ] );
154        }
155    }
156
157    /**
158     * Create a link on the page
159     * @param ParserOutput $parserOutput
160     * @param string &$text The text to link
161     * @param Title|null $title Link target title
162     * @return void
163     */
164    private function makeLink( ParserOutput $parserOutput, string &$text, ?Title $title ) {
165        if ( $title ) {
166            $parserOutput->addLink( $title );
167            $text = new GadgetDefinitionContentArmor(
168                Linker::link( $title, htmlspecialchars( '"' . $text . '"' ) )
169            );
170        }
171    }
172}