| Current File : /home/jvzmxxx/wiki/extensions/EventLogging/includes/JsonSchemaContent.php |
<?php
/**
* JSON Schema Content Model
*
* @file
* @ingroup Extensions
* @ingroup EventLogging
*
* @author Ori Livneh <ori@wikimedia.org>
*/
/**
* Represents the content of a JSON Schema article.
*/
class JsonSchemaContent extends JsonContent {
const DEFAULT_RECURSION_LIMIT = 3;
public function __construct( $text, $modelId = 'JsonSchema' ) {
parent::__construct( $text, $modelId );
}
/**
* Resolve a JSON reference to a schema.
* @param string $ref Schema reference with format 'Title/Revision'
* @return array|bool
*/
public static function resolve( $ref ) {
list( $title, $revId ) = explode( '/', $ref );
$rs = new RemoteSchema( $title, $revId );
return $rs->get();
}
/**
* Recursively resolve references in a schema.
* @param array $schema Schema object to expand
* @param int $recursionLimit Maximum recursion limit
* @return array Expanded schema object
*/
public static function expand( $schema,
$recursionLimit = JsonSchemaContent::DEFAULT_RECURSION_LIMIT ) {
return array_map( function ( $value ) use( $recursionLimit ) {
if ( is_array( $value ) && $recursionLimit > 0 ) {
if ( isset( $value['$ref'] ) ) {
$value = JsonSchemaContent::resolve( $value['$ref'] );
}
return JsonSchemaContent::expand( $value, $recursionLimit - 1 );
} else {
return $value;
}
}, $schema );
}
/**
* Decodes the JSON schema into a PHP associative array.
* @return array Schema array
*/
public function getJsonData() {
return FormatJson::decode( $this->getNativeData(), true );
}
/**
* @throws JsonSchemaException If content is invalid
* @return bool True if valid
*/
public function validate() {
$schema = $this->getJsonData();
if ( !is_array( $schema ) ) {
throw new JsonSchemaException( 'eventlogging-invalid-json' );
}
return EventLogging::schemaValidate( $schema );
}
/**
* @return bool Whether content is valid JSON Schema.
*/
public function isValid() {
try {
return parent::isValid() && $this->validate();
} catch ( JsonSchemaException $e ) {
return false;
}
}
/**
* Constructs HTML representation of a single key-value pair.
* Override this to support $ref
* @param string $key
* @param mixed $val
* @return string HTML
*/
public function objectRow( $key, $val ) {
if ( $key === '$ref' ) {
$valParts = explode( '/', $val, 2 );
if ( !isset( $valParts[1] ) ) {
$revId = $valParts[1];
$title = Revision::newFromId( $revId )->getTitle();
$link = Linker::link( $title, htmlspecialchars( $val ), [],
[ 'oldid' => $revId ] );
$th = Xml::elementClean( 'th', [], $key );
$td = Xml::tags( 'td', [ 'class' => 'value' ], $link );
return Html::rawElement( 'tr', [], $th . $td );
}
}
return parent::objectRow( $key, $val );
}
/**
* Generate generic PHP and JavaScript code strings showing how to
* use a schema.
* @param string $dbKey DB key of schema article
* @param int $revId Revision ID of schema article
* @return array Nested array with each sub-array having a language, header
* (message key), and code
*/
public function getCodeSamples( $dbKey, $revId ) {
return [
[
'language' => 'php',
'header' => 'eventlogging-code-sample-logging-on-server-side',
'code' => "EventLogging::logEvent( '$dbKey', $revId, \$event );",
], [
'language' => 'json',
'header' => 'eventlogging-code-sample-module-setup-json',
'code' => "{\n\t\"EventLoggingSchemas\": {\n\t\t\"$dbKey\": $revId\n\t}\n}",
], [
'language' => 'javascript',
'header' => 'eventlogging-code-sample-logging-on-client-side',
'code' => "mw.eventLog.logEvent( '{$dbKey}', { /* ... */ } );",
],
];
}
/**
* Wraps HTML representation of content.
*
* If the schema already exists and if the SyntaxHiglight GeSHi
* extension is installed, use it to render code snippets
* showing how to use schema.
*
* @see https://mediawiki.org/wiki/Extension:SyntaxHighlight_GeSHi
*
* @param Title $title
* @param int|null $revId Revision ID
* @param ParserOptions|null $options
* @param bool $generateHtml Whether or not to generate HTML
* @return ParserOutput
*/
public function getParserOutput( Title $title, $revId = null,
ParserOptions $options = null, $generateHtml = true ) {
$out = parent::getParserOutput( $title, $revId, $options, $generateHtml );
if ( $revId !== null && class_exists( 'SyntaxHighlight_GeSHi' ) ) {
$html = '';
$highlighter = new SyntaxHighlight_GeSHi();
foreach ( self::getCodeSamples( $title->getDBkey(), $revId ) as $sample ) {
$lang = $sample['language'];
$code = $sample['code'];
$highlighted = $highlighter->highlight( $code, $lang )->getValue();
$html .= Html::element( 'h2',
[],
wfMessage( $sample['header'] )->text()
) . $highlighted;
}
// The glyph is '< >' from the icon font 'Entypo' (see ../modules).
$html = Xml::tags( 'div', [ 'class' => 'mw-json-schema-code-glyph' ], '' ) .
Xml::tags( 'div', [ 'class' => 'mw-json-schema-code-samples' ], $html );
$out->setIndicator( 'schema-code-samples', $html );
$out->addModules( [ 'ext.eventLogging.jsonSchema', 'ext.pygments' ] );
$out->addModuleStyles( 'ext.eventLogging.jsonSchema.styles' );
}
return $out;
}
}