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