Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
21.62% covered (danger)
21.62%
8 / 37
42.86% covered (danger)
42.86%
3 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
JsonSchemaContent
21.62% covered (danger)
21.62%
8 / 37
42.86% covered (danger)
42.86%
3 / 7
94.37
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 resolve
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 expand
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 getJsonData
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 validate
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
 isValid
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getCodeSamples
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * JSON Schema Content Model
4 *
5 * @file
6 * @ingroup Extensions
7 * @ingroup EventLogging
8 *
9 * @author Ori Livneh <ori@wikimedia.org>
10 */
11
12namespace MediaWiki\Extension\EventLogging;
13
14use MediaWiki\Content\JsonContent;
15use MediaWiki\Extension\EventLogging\Libs\JsonSchemaValidation\JsonSchemaException;
16use MediaWiki\Json\FormatJson;
17
18/**
19 * Represents the content of a JSON Schema article.
20 */
21class JsonSchemaContent extends JsonContent {
22
23    private const DEFAULT_RECURSION_LIMIT = 3;
24
25    /** @inheritDoc */
26    public function __construct( $text, $modelId = 'JsonSchema' ) {
27        parent::__construct( $text, $modelId );
28    }
29
30    /**
31     * Resolve a JSON reference to a schema.
32     * @param string $ref Schema reference with format 'Title/Revision'
33     * @return array|bool
34     */
35    public static function resolve( $ref ) {
36        [ $title, $revId ] = explode( '/', $ref );
37        $rs = new RemoteSchema( $title, (int)$revId );
38        return $rs->get();
39    }
40
41    /**
42     * Recursively resolve references in a schema.
43     * @param array $schema Schema object to expand
44     * @param int $recursionLimit Maximum recursion limit
45     * @return array Expanded schema object
46     */
47    public static function expand( $schema,
48            $recursionLimit = self::DEFAULT_RECURSION_LIMIT ) {
49        return array_map( static function ( $value ) use( $recursionLimit ) {
50            if ( is_array( $value ) && $recursionLimit > 0 ) {
51                if ( isset( $value['$ref'] ) ) {
52                    $value = JsonSchemaContent::resolve( $value['$ref'] );
53                }
54                return JsonSchemaContent::expand( $value, $recursionLimit - 1 );
55            }
56            return $value;
57        }, $schema );
58    }
59
60    /**
61     * Decodes the JSON schema into a PHP associative array.
62     * @return array Schema array
63     */
64    public function getJsonData() {
65        return FormatJson::decode( $this->getText(), true );
66    }
67
68    /**
69     * @throws JsonSchemaException If content is invalid
70     * @return bool True if valid
71     */
72    public function validate() {
73        $schema = $this->getJsonData();
74        if ( !is_array( $schema ) ) {
75            throw new JsonSchemaException( 'eventlogging-invalid-json' );
76        }
77        return EventLogging::schemaValidate( $schema );
78    }
79
80    /**
81     * @return bool Whether content is valid JSON Schema.
82     */
83    public function isValid() {
84        try {
85            return parent::isValid() && $this->validate();
86        } catch ( JsonSchemaException $e ) {
87            return false;
88        }
89    }
90
91    /**
92     * Generate generic PHP and JavaScript code strings showing how to
93     * use a schema.
94     * @param string $dbKey DB key of schema article
95     * @param int $revId Revision ID of schema article
96     * @return array[] Nested array with each sub-array having a language, header
97     *  (message key), and code
98     */
99    public function getCodeSamples( $dbKey, $revId ) {
100        return [
101            [
102                'language' => 'php',
103                'header' => 'eventlogging-code-sample-logging-on-server-side',
104                'code' => "EventLogging::logEvent( '$dbKey', $revId, \$event );",
105            ], [
106                'language' => 'json',
107                'header' => 'eventlogging-code-sample-module-setup-json',
108                'code' => FormatJson::encode( [
109                    'attributes' => [ 'EventLogging' => [
110                        'Schemas' => [ $dbKey => $revId, ] ]
111                    ] ], "\t" ),
112            ], [
113                'language' => 'javascript',
114                'header' => 'eventlogging-code-sample-logging-on-client-side',
115                'code' => "mw.track( 'event.{$dbKey}', { /* ... */ } );",
116            ],
117        ];
118    }
119}