Skip to content
Snippets Groups Projects
Verified Commit 94e4d471 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3392903 by borisson_, Wim Leers, phenaproxima: Validate inputs of...

Issue #3392903 by borisson_, Wim Leers, phenaproxima: Validate inputs of TypeResolver::resolveExpression(): only allow %parent, %type and %key
parent 7df5d6a1
No related branches found
No related tags found
No related merge requests found
......@@ -75,7 +75,8 @@ public static function resolveDynamicTypeName(string $name, mixed $data): string
* The value the expression resolves to, or the given expression if it
* cannot be resolved.
*
* @todo Validate the expression in https://www.drupal.org/project/drupal/issues/3392903
* @throws \LogicException
* Exception thrown if $expression is not a valid dynamic type expression.
*/
public static function resolveExpression(string $expression, array|TypedDataInterface $data): string {
if ($data instanceof TypedDataInterface) {
......@@ -87,8 +88,16 @@ public static function resolveExpression(string $expression, array|TypedDataInte
}
$parts = explode('.', $expression);
$previous_name = NULL;
// Process each value part, one at a time.
while ($name = array_shift($parts)) {
if (str_starts_with($name, '%') && !in_array($name, ['%parent', '%key', '%type'], TRUE)) {
throw new \LogicException('`' . $expression . '` is not a valid dynamic type expression. Dynamic type expressions must contain at least `%parent`, `%key`, or `%type`.`');
}
if ($name === '%type' && $previous_name !== '%parent') {
throw new \LogicException('`%type` can only used when immediately preceded by `%parent` in `' . $expression . '`');
}
$previous_name = $name;
if (!is_array($data) || !isset($data[$name])) {
// Key not found, return original value
return $expression;
......
......@@ -64,7 +64,7 @@ public function testEntityTypeIdIsStatic(): void {
}
/**
* Tests getting the entity type ID from the parent property path.
* Tests getting the entity type ID.
*
* @param string $constraint_value
* The entity type ID to supply to the validation constraint. Must be a
......@@ -74,9 +74,9 @@ public function testEntityTypeIdIsStatic(): void {
* a bundle.
*
* @testWith ["%parent.entity_type_id", "entity_test_with_bundle"]
* ["%paren.entity_type_id", "%paren.entity_type_id"]
* ["%key", "bundle"]
*/
public function testEntityTypeIdFromParent(string $constraint_value, string $resolved_entity_type_id): void {
public function testDynamicEntityType(string $constraint_value, string $resolved_entity_type_id): void {
/** @var \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager */
$typed_data_manager = $this->container->get('typed_data_manager');
......
<?php
declare(strict_types=1);
namespace Drupal\Tests\Core\Config;
use Drupal\Core\Config\Schema\TypeResolver;
use Drupal\Tests\UnitTestCase;
/**
* @covers \Drupal\Core\Config\Schema\TypeResolver
* @group config
*/
class TypeResolverTest extends UnitTestCase {
/**
* @testWith ["[foo.%bar.qux]", "`foo.%bar.qux` is not a valid dynamic type expression. Dynamic type expressions must contain at least `%parent`, `%key`, or `%type`.`", {"foo": "foo"}]
* ["[%paren.field_type]", "`%paren.field_type` is not a valid dynamic type expression. Dynamic type expressions must contain at least `%parent`, `%key`, or `%type`."]
* ["[something.%type]", "`%type` can only used when immediately preceded by `%parent` in `something.%type`", {"something": "something"}]
*/
public function testInvalidType(string $name, string $message, array $data = []): void {
$this->expectException(\LogicException::class);
$this->expectExceptionMessage($message);
TypeResolver::resolveDynamicTypeName($name, $data);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment