X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2Fcontent%2FJsonContent.php;h=40d9277470f82b3385ce43cd32bab5d2c4ef60f4;hb=27d3f08d4e41ca5745c80a57afd441f9250db7e1;hp=df90f229f4e0c60aecd4a2bbcb8718adbd9f6236;hpb=d80c61f18147602c4caf39fa55d479e19208e177;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/content/JsonContent.php b/includes/content/JsonContent.php index df90f229f4..40d9277470 100644 --- a/includes/content/JsonContent.php +++ b/includes/content/JsonContent.php @@ -2,8 +2,6 @@ /** * JSON Content Model * - * This class requires the root structure to be an object (not primitives or arrays). - * * @file * * @author Ori Livneh @@ -41,7 +39,10 @@ class JsonContent extends TextContent { } /** - * Decodes the JSON string into a PHP object. + * Decodes the JSON string. + * + * Note that this parses it without casting objects to associative arrays. + * Objects and arrays are kept as distinguishable types in the PHP values. * * @return Status */ @@ -56,7 +57,7 @@ class JsonContent extends TextContent { * @return bool Whether content is valid. */ public function isValid() { - return $this->getData()->isGood() && is_object( $this->getData()->getValue() ); + return $this->getData()->isGood(); } /** @@ -67,7 +68,7 @@ class JsonContent extends TextContent { * @return string */ public function beautifyJSON() { - return FormatJson::encode( $this->getData()->getValue(), true ); + return FormatJson::encode( $this->getData()->getValue(), true, FormatJson::UTF8_OK ); } /** @@ -103,7 +104,7 @@ class JsonContent extends TextContent { // FIXME: WikiPage::doEditContent generates parser output before validation. // As such, native data may be invalid (though output is discarded later in that case). if ( $generateHtml && $this->isValid() ) { - $output->setText( $this->objectTable( $this->getData()->getValue() ) ); + $output->setText( $this->rootValueTable( $this->getData()->getValue() ) ); $output->addModuleStyles( 'mediawiki.content.json' ); } else { $output->setText( '' ); @@ -111,15 +112,41 @@ class JsonContent extends TextContent { } /** - * Construct an HTML representation of a JSON object. + * Construct HTML table representation of any JSON value. * - * Called recursively via valueCell(). + * See also valueCell, which is similar. + * + * @param mixed $val + * @return string HTML. + */ + protected function rootValueTable( $val ) { + if ( is_object( $val ) ) { + return $this->objectTable( $val ); + } + + if ( is_array( $val ) ) { + // Wrap arrays in another array so that they're visually boxed in a container. + // Otherwise they are visually indistinguishable from a single value. + return $this->arrayTable( [ $val ] ); + } + + return Html::rawElement( 'table', [ 'class' => 'mw-json mw-json-single-value' ], + Html::rawElement( 'tbody', [], + Html::rawElement( 'tr', [], + Html::element( 'td', [], $this->primitiveValue( $val ) ) + ) + ) + ); + } + + /** + * Create HTML table representing a JSON object. * * @param stdClass $mapping * @return string HTML */ protected function objectTable( $mapping ) { - $rows = array(); + $rows = []; $empty = true; foreach ( $mapping as $key => $val ) { @@ -127,39 +154,38 @@ class JsonContent extends TextContent { $empty = false; } if ( $empty ) { - $rows[] = Html::rawElement( 'tr', array(), - Html::element( 'td', array( 'class' => 'mw-json-empty' ), + $rows[] = Html::rawElement( 'tr', [], + Html::element( 'td', [ 'class' => 'mw-json-empty' ], wfMessage( 'content-json-empty-object' )->text() ) ); } - return Html::rawElement( 'table', array( 'class' => 'mw-json' ), - Html::rawElement( 'tbody', array(), join( "\n", $rows ) ) + return Html::rawElement( 'table', [ 'class' => 'mw-json' ], + Html::rawElement( 'tbody', [], implode( '', $rows ) ) ); } /** - * Construct HTML representation of a single key-value pair. + * Create HTML table row representing one object property. + * * @param string $key * @param mixed $val * @return string HTML. */ protected function objectRow( $key, $val ) { - $th = Xml::elementClean( 'th', array(), $key ); - $td = self::valueCell( $val ); - return Html::rawElement( 'tr', array(), $th . $td ); + $th = Html::element( 'th', [], $key ); + $td = $this->valueCell( $val ); + return Html::rawElement( 'tr', [], $th . $td ); } /** - * Constructs an HTML representation of a JSON array. - * - * Called recursively via valueCell(). + * Create HTML table representing a JSON array. * * @param array $mapping * @return string HTML */ protected function arrayTable( $mapping ) { - $rows = array(); + $rows = []; $empty = true; foreach ( $mapping as $val ) { @@ -167,45 +193,58 @@ class JsonContent extends TextContent { $empty = false; } if ( $empty ) { - $rows[] = Html::rawElement( 'tr', array(), - Html::element( 'td', array( 'class' => 'mw-json-empty' ), + $rows[] = Html::rawElement( 'tr', [], + Html::element( 'td', [ 'class' => 'mw-json-empty' ], wfMessage( 'content-json-empty-array' )->text() ) ); } - return Html::rawElement( 'table', array( 'class' => 'mw-json' ), - Html::rawElement( 'tbody', array(), join( "\n", $rows ) ) + return Html::rawElement( 'table', [ 'class' => 'mw-json' ], + Html::rawElement( 'tbody', [], implode( "\n", $rows ) ) ); } /** - * Construct HTML representation of a single array value. + * Create HTML table row representing the value in an array. + * * @param mixed $val * @return string HTML. */ protected function arrayRow( $val ) { - $td = self::valueCell( $val ); - return Html::rawElement( 'tr', array(), $td ); + $td = $this->valueCell( $val ); + return Html::rawElement( 'tr', [], $td ); } /** - * Construct HTML representation of a single value. + * Construct HTML table cell representing any JSON value. + * * @param mixed $val * @return string HTML. */ protected function valueCell( $val ) { if ( is_object( $val ) ) { - return Html::rawElement( 'td', array(), self::objectTable( $val ) ); + return Html::rawElement( 'td', [], $this->objectTable( $val ) ); } + if ( is_array( $val ) ) { - return Html::rawElement( 'td', array(), self::arrayTable( $val ) ); + return Html::rawElement( 'td', [], $this->arrayTable( $val ) ); } + + return Html::element( 'td', [ 'class' => 'value' ], $this->primitiveValue( $val ) ); + } + + /** + * Construct text representing a JSON primitive value. + * + * @param mixed $val + * @return string Text. + */ + protected function primitiveValue( $val ) { if ( is_string( $val ) ) { - $val = '"' . $val . '"'; - } else { - $val = FormatJson::encode( $val ); + // Don't FormatJson::encode for strings since we want quotes + // and new lines to render visually instead of escaped. + return '"' . $val . '"'; } - - return Xml::elementClean( 'td', array( 'class' => 'value' ), $val ); + return FormatJson::encode( $val ); } }