Issue #3462156 by niklan, vensires, smustgrave, quietone, wim leers: Throw an exception if a component property's `type` contains non-string values

merge-requests/9874/merge
Lee Rowlands 2024-10-24 11:45:49 +10:00
parent 833e599d18
commit f0b4dd2ba4
No known key found for this signature in database
GPG Key ID: 2B829A3DF9204DC4
2 changed files with 49 additions and 8 deletions

View File

@ -81,6 +81,28 @@ class ComponentValidator {
if (($schema['properties'] ?? NULL) === []) {
$schema['properties'] = new \stdClass();
}
// Ensure that all property types are strings. For example, a null value
// will not automatically convert to 'null', which will lead to a PHP error
// that is hard to trace back to the property.
$non_string_props = [];
\array_walk($prop_names, function (string $prop) use (&$non_string_props, $schema) {
$type = $schema['properties'][$prop]['type'];
$types = !\is_array($type) ? [$type] : $type;
$non_string_types = \array_filter($types, static fn (mixed $type) => !\is_string($type));
if ($non_string_types) {
$non_string_props[] = $prop;
}
});
if ($non_string_props) {
throw new InvalidComponentException(\sprintf(
'The component "%s" uses non-string types for properties: %s.',
$definition['id'],
\implode(', ', $non_string_props),
));
}
$classes_per_prop = $this->getClassProps($schema);
$missing_class_errors = [];
foreach ($classes_per_prop as $prop_name => $class_types) {

View File

@ -65,24 +65,43 @@ class ComponentValidatorTest extends TestCase {
/**
* Data provider with invalid component definitions.
*
* @return array
* The data.
* @return \Generator
* Returns the generator with the invalid definitions.
*/
public static function dataProviderValidateDefinitionInvalid(): array {
public static function dataProviderValidateDefinitionInvalid(): \Generator {
$valid_cta = static::loadComponentDefinitionFromFs('my-cta');
$cta_with_missing_required = $valid_cta;
unset($cta_with_missing_required['path']);
yield 'missing required' => [$cta_with_missing_required];
$cta_with_invalid_class = $valid_cta;
$cta_with_invalid_class['props']['properties']['attributes']['type'] = 'Drupal\Foo\Invalid';
yield 'invalid class' => [$cta_with_invalid_class];
$cta_with_invalid_enum = array_merge(
$valid_cta,
['extension_type' => 'invalid'],
);
return [
[$cta_with_missing_required],
[$cta_with_invalid_class],
[$cta_with_invalid_enum],
];
yield 'invalid enum' => [$cta_with_invalid_enum];
// A list of property types that are not strings, but can be provided via
// YAML.
$non_string_types = [NULL, 123, 123.45, TRUE];
foreach ($non_string_types as $non_string_type) {
$cta_with_non_string_prop_type = $valid_cta;
$cta_with_non_string_prop_type['props']['properties']['text']['type'] = $non_string_type;
yield "non string type ($non_string_type)" => [$cta_with_non_string_prop_type];
// Same, but as a part of the list of allowed types.
$cta_with_non_string_prop_type['props']['properties']['text']['type'] = ['string', $non_string_type];
yield "non string type ($non_string_type) in a list of types" => [$cta_with_non_string_prop_type];
}
// The array is a valid value for the 'type' parameter, but it is not
// allowed as the allowed type.
$cta_with_non_string_prop_type['props']['properties']['text']['type'] = ['string', []];
yield 'non string type (Array)' => [$cta_with_non_string_prop_type];
}
/**