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