Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
8.33% covered (danger)
8.33%
5 / 60
36.36% covered (danger)
36.36%
4 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
JsonContent
8.47% covered (danger)
8.47%
5 / 59
36.36% covered (danger)
36.36%
4 / 11
326.68
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getData
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 isValid
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 beautifyJSON
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 rootValueTable
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 objectTable
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
 objectRow
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 arrayTable
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
 arrayRow
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 valueCell
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 primitiveValue
0.00% covered (danger)
0.00%
0 / 3
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\Content;
22
23use MediaWiki\Html\Html;
24use MediaWiki\Json\FormatJson;
25use MediaWiki\Status\Status;
26
27/**
28 * JSON text content that can be viewed and edit directly by users.
29 *
30 * @newable
31 * @stable to extend
32 * @since 1.24
33 * @ingroup Content
34 * @author Ori Livneh <ori@wikimedia.org>
35 * @author Kunal Mehta <legoktm@gmail.com>
36 */
37class JsonContent extends TextContent {
38
39    /**
40     * @since 1.25
41     * @var Status
42     */
43    protected $jsonParse;
44
45    /**
46     * @param string $text JSON
47     * @param string $modelId
48     * @stable to call
49     */
50    public function __construct( $text, $modelId = CONTENT_MODEL_JSON ) {
51        parent::__construct( $text, $modelId );
52    }
53
54    /**
55     * Decodes the JSON string.
56     *
57     * Note that this parses it without casting objects to associative arrays.
58     * Objects and arrays are kept as distinguishable types in the PHP values.
59     *
60     * @return Status
61     */
62    public function getData() {
63        $this->jsonParse ??= FormatJson::parse( $this->getText() );
64        return $this->jsonParse;
65    }
66
67    /**
68     * @return bool Whether content is valid.
69     */
70    public function isValid() {
71        return $this->getData()->isGood();
72    }
73
74    /**
75     * Pretty-print JSON.
76     *
77     * If called before validation, it may return JSON "null".
78     *
79     * @return string
80     */
81    public function beautifyJSON() {
82        return FormatJson::encode( $this->getData()->getValue(), "\t", FormatJson::UTF8_OK );
83    }
84
85    /**
86     * Construct HTML table representation of any JSON value.
87     *
88     * See also valueCell, which is similar.
89     *
90     * @param mixed $val
91     * @return string HTML.
92     */
93    public function rootValueTable( $val ) {
94        if ( is_object( $val ) ) {
95            $table = $this->objectTable( $val );
96
97        } elseif ( is_array( $val ) ) {
98            // Wrap arrays in another array so that they're visually boxed in a container.
99            // Otherwise they are visually indistinguishable from a single value.
100            $table = $this->arrayTable( [ $val ] );
101
102        } else {
103            $table = Html::rawElement( 'table', [ 'class' => [ 'mw-json', 'mw-json-single-value' ] ],
104                Html::rawElement( 'tbody', [],
105                    Html::rawElement( 'tr', [],
106                        Html::element( 'td', [], $this->primitiveValue( $val ) )
107                    )
108                )
109            );
110        }
111
112        return Html::rawElement( 'div', [ 'class' => 'noresize' ], $table );
113    }
114
115    /**
116     * Create HTML table representing a JSON object.
117     *
118     * @param \stdClass $mapping
119     * @return string HTML
120     */
121    protected function objectTable( $mapping ) {
122        $rows = [];
123        $empty = true;
124
125        foreach ( $mapping as $key => $val ) {
126            $rows[] = $this->objectRow( $key, $val );
127            $empty = false;
128        }
129        if ( $empty ) {
130            $rows[] = Html::rawElement( 'tr', [],
131                Html::element( 'td', [ 'class' => 'mw-json-empty' ],
132                    wfMessage( 'content-json-empty-object' )->text()
133                )
134            );
135        }
136        return Html::rawElement( 'table', [ 'class' => 'mw-json' ],
137            Html::rawElement( 'tbody', [], implode( '', $rows ) )
138        );
139    }
140
141    /**
142     * Create HTML table row representing one object property.
143     *
144     * @param string $key
145     * @param mixed $val
146     * @return string HTML.
147     */
148    protected function objectRow( $key, $val ) {
149        $thContent = Html::element( 'span', [], $key );
150        $th = Html::rawElement( 'th', [], $thContent );
151        $td = $this->valueCell( $val );
152        return Html::rawElement( 'tr', [], $th . $td );
153    }
154
155    /**
156     * Create HTML table representing a JSON array.
157     *
158     * @param array $mapping
159     * @return string HTML
160     */
161    protected function arrayTable( $mapping ) {
162        $rows = [];
163        $empty = true;
164
165        foreach ( $mapping as $val ) {
166            $rows[] = $this->arrayRow( $val );
167            $empty = false;
168        }
169        if ( $empty ) {
170            $rows[] = Html::rawElement( 'tr', [],
171                Html::element( 'td', [ 'class' => 'mw-json-empty' ],
172                    wfMessage( 'content-json-empty-array' )->text()
173                )
174            );
175        }
176        return Html::rawElement( 'table', [ 'class' => 'mw-json' ],
177            Html::rawElement( 'tbody', [], implode( "\n", $rows ) )
178        );
179    }
180
181    /**
182     * Create HTML table row representing the value in an array.
183     *
184     * @param mixed $val
185     * @return string HTML.
186     */
187    protected function arrayRow( $val ) {
188        $td = $this->valueCell( $val );
189        return Html::rawElement( 'tr', [], $td );
190    }
191
192    /**
193     * Construct HTML table cell representing any JSON value.
194     *
195     * @param mixed $val
196     * @return string HTML.
197     */
198    protected function valueCell( $val ) {
199        if ( is_object( $val ) ) {
200            return Html::rawElement( 'td', [], $this->objectTable( $val ) );
201        }
202
203        if ( is_array( $val ) ) {
204            return Html::rawElement( 'td', [], $this->arrayTable( $val ) );
205        }
206
207        return Html::element( 'td', [ 'class' => 'mw-json-value' ], $this->primitiveValue( $val ) );
208    }
209
210    /**
211     * Construct text representing a JSON primitive value.
212     *
213     * @param mixed $val
214     * @return string Text.
215     */
216    protected function primitiveValue( $val ) {
217        if ( is_string( $val ) ) {
218            // Don't FormatJson::encode for strings since we want quotes
219            // and new lines to render visually instead of escaped.
220            return '"' . $val . '"';
221        }
222        return FormatJson::encode( $val );
223    }
224}
225/** @deprecated class alias since 1.43 */
226class_alias( JsonContent::class, 'JsonContent' );