]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/registration/ExtensionJsonValidator.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / includes / registration / ExtensionJsonValidator.php
1 <?php
2
3 /**
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  * http://www.gnu.org/copyleft/gpl.html
18  *
19  * @file
20  */
21
22 use Composer\Spdx\SpdxLicenses;
23 use JsonSchema\Validator;
24 use Seld\JsonLint\JsonParser;
25 use Seld\JsonLint\ParsingException;
26
27 /**
28  * @since 1.29
29  */
30 class ExtensionJsonValidator {
31
32         /**
33          * @var callable
34          */
35         private $missingDepCallback;
36
37         /**
38          * @param callable $missingDepCallback
39          */
40         public function __construct( callable $missingDepCallback ) {
41                 $this->missingDepCallback = $missingDepCallback;
42         }
43
44         /**
45          * @return bool
46          */
47         public function checkDependencies() {
48                 if ( !class_exists( Validator::class ) ) {
49                         call_user_func( $this->missingDepCallback,
50                                 'The JsonSchema library cannot be found, please install it through composer.'
51                         );
52                         return false;
53                 } elseif ( !class_exists( SpdxLicenses::class ) ) {
54                         call_user_func( $this->missingDepCallback,
55                                 'The spdx-licenses library cannot be found, please install it through composer.'
56                         );
57                         return false;
58                 } elseif ( !class_exists( JsonParser::class ) ) {
59                         call_user_func( $this->missingDepCallback,
60                                 'The JSON lint library cannot be found, please install it through composer.'
61                         );
62                 }
63
64                 return true;
65         }
66
67         /**
68          * @param string $path file to validate
69          * @return bool true if passes validation
70          * @throws ExtensionJsonValidationError on any failure
71          */
72         public function validate( $path ) {
73                 $contents = file_get_contents( $path );
74                 $jsonParser = new JsonParser();
75                 try {
76                         $data = $jsonParser->parse( $contents, JsonParser::DETECT_KEY_CONFLICTS );
77                 } catch ( ParsingException $e ) {
78                         if ( $e instanceof \Seld\JsonLint\DuplicateKeyException ) {
79                                 throw new ExtensionJsonValidationError( $e->getMessage() );
80                         }
81                         throw new ExtensionJsonValidationError( "$path is not valid JSON" );
82                 }
83
84                 if ( !isset( $data->manifest_version ) ) {
85                         throw new ExtensionJsonValidationError(
86                                 "$path does not have manifest_version set." );
87                 }
88
89                 $version = $data->manifest_version;
90                 $schemaPath = __DIR__ . "/../../docs/extension.schema.v$version.json";
91
92                 // Not too old
93                 if ( $version < ExtensionRegistry::OLDEST_MANIFEST_VERSION ) {
94                         throw new ExtensionJsonValidationError(
95                                 "$path is using a non-supported schema version"
96                         );
97                 } elseif ( $version > ExtensionRegistry::MANIFEST_VERSION ) {
98                         throw new ExtensionJsonValidationError(
99                                 "$path is using a non-supported schema version"
100                         );
101                 }
102
103                 $licenseError = false;
104                 // Check if it's a string, if not, schema validation will display an error
105                 if ( isset( $data->{'license-name'} ) && is_string( $data->{'license-name'} ) ) {
106                         $licenses = new SpdxLicenses();
107                         $valid = $licenses->validate( $data->{'license-name'} );
108                         if ( !$valid ) {
109                                 $licenseError = '[license-name] Invalid SPDX license identifier, '
110                                         . 'see <https://spdx.org/licenses/>';
111                         }
112                 }
113
114                 $validator = new Validator;
115                 $validator->check( $data, (object)[ '$ref' => 'file://' . $schemaPath ] );
116                 if ( $validator->isValid() && !$licenseError ) {
117                         // All good.
118                         return true;
119                 } else {
120                         $out = "$path did not pass validation.\n";
121                         foreach ( $validator->getErrors() as $error ) {
122                                 $out .= "[{$error['property']}] {$error['message']}\n";
123                         }
124                         if ( $licenseError ) {
125                                 $out .= "$licenseError\n";
126                         }
127                         throw new ExtensionJsonValidationError( $out );
128                 }
129         }
130 }