123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- <?php
- /**
- * JSON Content Model
- *
- * @file
- *
- * @author Ori Livneh <ori@wikimedia.org>
- * @author Kunal Mehta <legoktm@gmail.com>
- */
- /**
- * Represents the content of a JSON content.
- * @since 1.24
- */
- class JsonContent extends TextContent {
- /**
- * @since 1.25
- * @var Status
- */
- protected $jsonParse;
- /**
- * @param string $text JSON
- * @param string $modelId
- */
- public function __construct( $text, $modelId = CONTENT_MODEL_JSON ) {
- parent::__construct( $text, $modelId );
- }
- /**
- * Decodes the JSON into a PHP associative array.
- *
- * @deprecated since 1.25 Use getData instead.
- * @return array|null
- */
- public function getJsonData() {
- wfDeprecated( __METHOD__, '1.25' );
- return FormatJson::decode( $this->getNativeData(), true );
- }
- /**
- * 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
- */
- public function getData() {
- if ( $this->jsonParse === null ) {
- $this->jsonParse = FormatJson::parse( $this->getNativeData() );
- }
- return $this->jsonParse;
- }
- /**
- * @return bool Whether content is valid.
- */
- public function isValid() {
- return $this->getData()->isGood();
- }
- /**
- * Pretty-print JSON.
- *
- * If called before validation, it may return JSON "null".
- *
- * @return string
- */
- public function beautifyJSON() {
- return FormatJson::encode( $this->getData()->getValue(), true, FormatJson::UTF8_OK );
- }
- /**
- * Beautifies JSON prior to save.
- *
- * @param Title $title
- * @param User $user
- * @param ParserOptions $popts
- * @return JsonContent
- */
- public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
- // FIXME: WikiPage::doEditContent invokes PST before validation. As such, native data
- // may be invalid (though PST result is discarded later in that case).
- if ( !$this->isValid() ) {
- return $this;
- }
- return new static( self::normalizeLineEndings( $this->beautifyJSON() ) );
- }
- /**
- * Set the HTML and add the appropriate styles.
- *
- * @param Title $title
- * @param int $revId
- * @param ParserOptions $options
- * @param bool $generateHtml
- * @param ParserOutput &$output
- */
- protected function fillParserOutput( Title $title, $revId,
- ParserOptions $options, $generateHtml, ParserOutput &$output
- ) {
- // 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->rootValueTable( $this->getData()->getValue() ) );
- $output->addModuleStyles( 'mediawiki.content.json' );
- } else {
- $output->setText( '' );
- }
- }
- /**
- * Construct HTML table representation of any JSON value.
- *
- * 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 = [];
- $empty = true;
- foreach ( $mapping as $key => $val ) {
- $rows[] = $this->objectRow( $key, $val );
- $empty = false;
- }
- if ( $empty ) {
- $rows[] = Html::rawElement( 'tr', [],
- Html::element( 'td', [ 'class' => 'mw-json-empty' ],
- wfMessage( 'content-json-empty-object' )->text()
- )
- );
- }
- return Html::rawElement( 'table', [ 'class' => 'mw-json' ],
- Html::rawElement( 'tbody', [], implode( '', $rows ) )
- );
- }
- /**
- * Create HTML table row representing one object property.
- *
- * @param string $key
- * @param mixed $val
- * @return string HTML.
- */
- protected function objectRow( $key, $val ) {
- $th = Html::element( 'th', [], $key );
- $td = $this->valueCell( $val );
- return Html::rawElement( 'tr', [], $th . $td );
- }
- /**
- * Create HTML table representing a JSON array.
- *
- * @param array $mapping
- * @return string HTML
- */
- protected function arrayTable( $mapping ) {
- $rows = [];
- $empty = true;
- foreach ( $mapping as $val ) {
- $rows[] = $this->arrayRow( $val );
- $empty = false;
- }
- if ( $empty ) {
- $rows[] = Html::rawElement( 'tr', [],
- Html::element( 'td', [ 'class' => 'mw-json-empty' ],
- wfMessage( 'content-json-empty-array' )->text()
- )
- );
- }
- return Html::rawElement( 'table', [ 'class' => 'mw-json' ],
- Html::rawElement( 'tbody', [], implode( "\n", $rows ) )
- );
- }
- /**
- * Create HTML table row representing the value in an array.
- *
- * @param mixed $val
- * @return string HTML.
- */
- protected function arrayRow( $val ) {
- $td = $this->valueCell( $val );
- return Html::rawElement( 'tr', [], $td );
- }
- /**
- * 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', [], $this->objectTable( $val ) );
- }
- if ( is_array( $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 ) ) {
- // Don't FormatJson::encode for strings since we want quotes
- // and new lines to render visually instead of escaped.
- return '"' . $val . '"';
- }
- return FormatJson::encode( $val );
- }
- }
|