Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
JCDefaultContentView
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 7
600
0.00% covered (danger)
0.00%
0 / 1
 valueToHtml
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDefault
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 renderValue
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
110
 renderTableRow
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 renderRowContent
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 isContainer
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 isList
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2
3namespace JsonConfig;
4
5use FormatJson;
6use MediaWiki\Html\Html;
7use MediaWiki\Page\PageReference;
8use MediaWiki\Parser\ParserOutput;
9use ParserOptions;
10
11/**
12 * This class is used in case when there is no custom view defined for JCContent object
13 * @package JsonConfig
14 */
15class JCDefaultContentView extends JCContentView {
16
17    /**
18     * Render JCContent object as HTML
19     * Called from an override of AbstractContent::fillParserOutput()
20     *
21     * Render JCContent object as HTML - replaces valueToHtml()
22     * @param JCContent $content
23     * @param PageReference $page Context title for parsing
24     * @param int|null $revId Revision ID (for {{REVISIONID}})
25     * @param ParserOptions $options Parser options
26     * @param bool $generateHtml Whether or not to generate HTML
27     * @param ParserOutput &$output The output object to fill (reference).
28     * @return string
29     */
30    public function valueToHtml(
31        JCContent $content, PageReference $page, $revId, ParserOptions $options, $generateHtml,
32         ParserOutput &$output
33    ) {
34        return $this->renderValue( $content, $content->getData(), [] );
35    }
36
37    /**
38     * Returns default content for this object
39     * @param string $modelId
40     * @return string
41     */
42    public function getDefault( $modelId ) {
43        return "{\n}";
44    }
45
46    /**
47     * Constructs an HTML representation of a JSON object.
48     * @param JCContent $content
49     * @param mixed $data
50     * @param array $path path to this field
51     * @return string HTML.
52     */
53    public function renderValue( JCContent $content, $data, array $path ) {
54        $isList = $this->isList( $content, $data, $path );
55        $isContainer = !$isList && $this->isContainer( $content, $data, $path );
56        if ( $isList || $isContainer ) {
57            $rows = [];
58            $level = count( $path );
59            foreach ( $data as $k => $v ) {
60                $path[$level] = $k;
61                if ( $isList ) {
62                    $rows[] = $this->renderValue( $content, $v, $path );
63                } else {
64                    $rows[] = $this->renderTableRow( $content, $v, $path );
65                }
66            }
67            if ( !$rows ) {
68                $res = '';
69            } elseif ( $isList ) {
70                $res = implode( ', ', $rows );
71                // HACK: The space prevents caller from treating it as a complex value
72                if ( str_starts_with( $res, '<' ) ) {
73                    $res = ' ' . $res;
74                }
75            } else {
76                $res =
77                    Html::rawElement( 'table', [ 'class' => 'mw-jsonconfig' ],
78                        Html::rawElement( 'tbody', [], implode( "\n", $rows ) ) );
79            }
80        } else {
81            $res = is_string( $data ) ? $data : FormatJson::encode( $data );
82            $res = htmlspecialchars( $res );
83        }
84
85        return $res;
86    }
87
88    /**
89     * Convert $data into a table row, returning <tr>...</tr> element.
90     * @param JCContent $content
91     * @param mixed $data treats it as opaque - renderValue will know how to handle it
92     * @param array $path path to this field
93     * @return string
94     */
95    public function renderTableRow( JCContent $content, $data, array $path ) {
96        $content = $this->renderRowContent( $content, $data, $path );
97        return Html::rawElement( 'tr', [], $content );
98    }
99
100    /**
101     * Converts $data into the content of the <tr>...</tr> tag.
102     * By default returns <th> with the last path element and <td> with the renderValue() result.
103     * @param JCContent $content
104     * @param mixed $data treats it as opaque - renderValue will know how to handle it
105     * @param array $path
106     * @return string
107     */
108    public function renderRowContent( JCContent $content, $data, array $path ) {
109        $key = end( $path );
110        $th = is_string( $key ) ? Html::element( 'th', [], $key ) : '';
111
112        $tdVal = $this->renderValue( $content, $data, $path );
113        // If html begins with a '<', its a complex object, and should not have a class
114        $attribs = [];
115        if ( !str_starts_with( $tdVal, '<' ) ) {
116            $attribs['class'] = 'mw-jsonconfig-value';
117        }
118        $td = Html::rawElement( 'td', $attribs, $tdVal );
119
120        return $th . $td;
121    }
122
123    /**
124     * Determine if data is a container and should be rendered as a complex structure
125     * @param JCContent $content
126     * @param array|\stdClass $data
127     * @param array $path
128     * @return bool
129     */
130    public function isContainer(
131        /** @noinspection PhpUnusedParameterInspection */
132        JCContent $content, $data, array $path
133    ) {
134        return is_array( $data ) || is_object( $data );
135    }
136
137    /**
138     * Determine if data is a special container that needs to be rendered as a comma-separated list.
139     * By default,
140     * @param JCContent $content
141     * @param array|\stdClass $data
142     * @param array $path
143     * @return bool
144     */
145    public function isList(
146        /** @noinspection PhpUnusedParameterInspection */
147        JCContent $content, $data, array $path
148    ) {
149        if ( !is_array( $data ) ) {
150            return false;
151        }
152        foreach ( $data as $k => $v ) {
153            if ( !is_int( $k ) || !( is_string( $v ) || is_numeric( $v ) ) ) {
154                return false;
155            }
156        }
157        return true;
158    }
159}