2015-08-03 06:37:32 +00:00
|
|
|
<?php
|
|
|
|
|
2022-02-06 18:54:47 +00:00
|
|
|
namespace MediaWiki\Extension\Gadgets\Content;
|
|
|
|
|
2024-01-06 16:45:07 +00:00
|
|
|
use MediaWiki\Status\Status;
|
2022-02-06 18:54:47 +00:00
|
|
|
|
2015-08-03 06:37:32 +00:00
|
|
|
/**
|
|
|
|
* Class responsible for validating Gadget definition contents
|
|
|
|
*
|
|
|
|
* @todo maybe this should use a formal JSON schema validator or something
|
|
|
|
*/
|
|
|
|
class GadgetDefinitionValidator {
|
|
|
|
/**
|
2020-12-17 19:07:37 +00:00
|
|
|
* @var array Validation metadata.
|
2017-05-30 18:38:47 +00:00
|
|
|
* 'foo.bar.baz' => [ 'type check callback',
|
|
|
|
* 'type name' [, 'member type check callback', 'member type name'] ]
|
2015-08-03 06:37:32 +00:00
|
|
|
*/
|
2016-12-28 10:25:47 +00:00
|
|
|
protected static $propertyValidation = [
|
|
|
|
'settings' => [ 'is_array', 'array' ],
|
|
|
|
'settings.rights' => [ 'is_array', 'array' , 'is_string', 'string' ],
|
|
|
|
'settings.default' => [ 'is_bool', 'boolean' ],
|
|
|
|
'settings.hidden' => [ 'is_bool', 'boolean' ],
|
2021-10-17 13:05:15 +00:00
|
|
|
'settings.package' => [ 'is_bool', 'boolean' ],
|
2023-12-16 08:44:06 +00:00
|
|
|
'settings.skins' => [ 'is_array', 'array', 'is_string', 'string' ],
|
2021-12-14 13:10:22 +00:00
|
|
|
'settings.actions' => [ 'is_array', 'array', 'is_string', 'string' ],
|
2023-12-16 08:44:06 +00:00
|
|
|
'settings.namespaces' => [ 'is_array', 'array', 'is_int', 'integer' ],
|
2023-05-22 08:41:15 +00:00
|
|
|
'settings.contentModels' => [ 'is_array', 'array', 'is_string', 'string' ],
|
2016-12-28 10:25:47 +00:00
|
|
|
'settings.category' => [ 'is_string', 'string' ],
|
2022-01-11 09:03:44 +00:00
|
|
|
'settings.supportsUrlLoad' => [ 'is_bool', 'boolean' ],
|
2022-01-30 13:15:25 +00:00
|
|
|
'settings.requiresES6' => [ 'is_bool', 'boolean' ],
|
2016-12-28 10:25:47 +00:00
|
|
|
'module' => [ 'is_array', 'array' ],
|
2023-12-16 08:44:06 +00:00
|
|
|
'module.pages' => [ 'is_array', 'array', [ __CLASS__, 'isValidTitleSuffix' ], '.js, .css or .json page' ],
|
2016-12-28 10:25:47 +00:00
|
|
|
'module.dependencies' => [ 'is_array', 'array', 'is_string', 'string' ],
|
2016-11-18 04:54:17 +00:00
|
|
|
'module.peers' => [ 'is_array', 'array', 'is_string', 'string' ],
|
2016-12-28 10:25:47 +00:00
|
|
|
'module.messages' => [ 'is_array', 'array', 'is_string', 'string' ],
|
2023-12-16 08:44:06 +00:00
|
|
|
'module.type' => [ [ __CLASS__, 'isValidType' ], 'general or styles' ],
|
2016-12-28 10:25:47 +00:00
|
|
|
];
|
2015-08-03 06:37:32 +00:00
|
|
|
|
2023-12-16 08:44:06 +00:00
|
|
|
public static function isValidTitleSuffix( string $title ): bool {
|
|
|
|
return str_ends_with( $title, '.js' ) || str_ends_with( $title, '.css' ) || str_ends_with( $title, '.json' );
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function isValidType( string $type ): bool {
|
|
|
|
return $type === '' || $type === 'general' || $type === 'styles';
|
2015-08-03 06:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check the validity of the given properties array
|
|
|
|
* @param array $properties Return value of FormatJson::decode( $blob, true )
|
|
|
|
* @param bool $tolerateMissing If true, don't complain about missing keys
|
|
|
|
* @return Status object with error message if applicable
|
|
|
|
*/
|
|
|
|
public function validate( array $properties, $tolerateMissing = false ) {
|
|
|
|
foreach ( self::$propertyValidation as $property => $validation ) {
|
|
|
|
$path = explode( '.', $property );
|
|
|
|
$val = $properties;
|
|
|
|
|
|
|
|
// Walk down and verify that the path from the root to this property exists
|
|
|
|
foreach ( $path as $p ) {
|
|
|
|
if ( !array_key_exists( $p, $val ) ) {
|
|
|
|
if ( $tolerateMissing ) {
|
|
|
|
// Skip validation of this property altogether
|
|
|
|
continue 2;
|
|
|
|
}
|
2021-10-09 00:34:45 +00:00
|
|
|
|
|
|
|
return Status::newFatal( 'gadgets-validate-notset', $property );
|
2015-08-03 06:37:32 +00:00
|
|
|
}
|
|
|
|
$val = $val[$p];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do the actual validation of this property
|
|
|
|
$func = $validation[0];
|
|
|
|
if ( !call_user_func( $func, $val ) ) {
|
|
|
|
return Status::newFatal(
|
2021-10-09 00:34:45 +00:00
|
|
|
'gadgets-validate-wrongtype',
|
|
|
|
$property,
|
|
|
|
$validation[1],
|
|
|
|
gettype( $val )
|
2015-08-03 06:37:32 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-12-21 08:40:05 +00:00
|
|
|
if ( isset( $validation[2] ) && isset( $validation[3] ) && is_array( $val ) ) {
|
2015-08-03 06:37:32 +00:00
|
|
|
// Descend into the array and check the type of each element
|
|
|
|
$func = $validation[2];
|
|
|
|
foreach ( $val as $i => $v ) {
|
|
|
|
if ( !call_user_func( $func, $v ) ) {
|
|
|
|
return Status::newFatal(
|
2021-10-09 00:34:45 +00:00
|
|
|
'gadgets-validate-wrongtype',
|
|
|
|
"{$property}[{$i}]",
|
|
|
|
$validation[3],
|
|
|
|
gettype( $v )
|
2015-08-03 06:37:32 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status::newGood();
|
|
|
|
}
|
|
|
|
}
|