Issue #3497061 by phenaproxima, alexpott: Allow recipe input values in array keys
parent
0348fc5148
commit
5db4867689
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace Drupal\Core\Recipe;
|
||||
|
||||
use Drupal\Core\Config\Action\ConfigActionException;
|
||||
use Drupal\Core\Config\ConfigManagerInterface;
|
||||
use Drupal\Core\Config\FileStorage;
|
||||
use Drupal\Core\Config\InstallStorage;
|
||||
use Drupal\Core\Config\StorageInterface;
|
||||
|
@ -93,11 +95,14 @@ final class RecipeRunner {
|
|||
* The recipe being applied.
|
||||
*/
|
||||
protected static function processConfiguration(Recipe $recipe): void {
|
||||
/** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
|
||||
$config_manager = \Drupal::service(ConfigManagerInterface::class);
|
||||
|
||||
$config_installer = new RecipeConfigInstaller(
|
||||
\Drupal::service('config.factory'),
|
||||
\Drupal::service('config.storage'),
|
||||
\Drupal::service('config.typed'),
|
||||
\Drupal::service('config.manager'),
|
||||
$config_manager,
|
||||
\Drupal::service('event_dispatcher'),
|
||||
NULL,
|
||||
\Drupal::service('extension.path.resolver'));
|
||||
|
@ -118,6 +123,13 @@ final class RecipeRunner {
|
|||
/** @var \Drupal\Core\Config\Action\ConfigActionManager $config_action_manager */
|
||||
$config_action_manager = \Drupal::service('plugin.manager.config_action');
|
||||
foreach ($config->config['actions'] as $config_name => $actions) {
|
||||
// If this config name contains an input value, it must begin with the
|
||||
// config prefix of a known entity type.
|
||||
if (str_contains($config_name, '${') && empty($config_manager->getEntityTypeIdByName($config_name))) {
|
||||
throw new ConfigActionException("The entity type for the config name '$config_name' could not be identified.");
|
||||
}
|
||||
$config_name = str_replace($keys, $replace, $config_name);
|
||||
|
||||
foreach ($actions as $action_id => $data) {
|
||||
$config_action_manager->applyAction($action_id, $config_name, static::replaceInputValues($data, $replace));
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Drupal\KernelTests\Core\Recipe;
|
|||
|
||||
use Drupal\Component\Uuid\UuidInterface;
|
||||
use Drupal\contact\Entity\ContactForm;
|
||||
use Drupal\Core\Config\Action\ConfigActionException;
|
||||
use Drupal\Core\Recipe\ConsoleInputCollector;
|
||||
use Drupal\Core\Recipe\InputCollectorInterface;
|
||||
use Drupal\Core\Recipe\Recipe;
|
||||
|
@ -14,6 +15,7 @@ use Drupal\Core\TypedData\DataDefinitionInterface;
|
|||
use Drupal\Core\TypedData\TypedDataInterface;
|
||||
use Drupal\FunctionalTests\Core\Recipe\RecipeTestTrait;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Style\StyleInterface;
|
||||
use Symfony\Component\Validator\Exception\ValidationFailedException;
|
||||
|
@ -229,4 +231,45 @@ YAML
|
|||
$this->assertSame('int is 1234, bool is and float is 3.141', $config->get('slogan'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using input values in entity IDs for config actions.
|
||||
*/
|
||||
public function testInputInConfigEntityIds(): void {
|
||||
$this->assertFalse(\Drupal::moduleHandler()->moduleExists('node'));
|
||||
|
||||
$collector = new class () implements InputCollectorInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collectValue(string $name, DataDefinitionInterface $definition, mixed $default_value): mixed {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
};
|
||||
$recipe = Recipe::createFromDirectory('core/tests/fixtures/recipes/input_test');
|
||||
$recipe->input->collectAll($collector);
|
||||
RecipeRunner::processRecipe($recipe);
|
||||
$this->assertInstanceOf(NodeType::class, NodeType::load('test'));
|
||||
|
||||
// Using an input placeholder in a non-identifying part of the config entity
|
||||
// ID should cause an exception.
|
||||
$recipe = $this->createRecipe([
|
||||
'name' => 'Invalid use of an input in config entity ID',
|
||||
'config' => [
|
||||
'actions' => [
|
||||
'node.${anything}.test' => [
|
||||
'createIfNotExists' => [
|
||||
'id' => 'test',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$recipe->input->collectAll($collector);
|
||||
$this->expectException(ConfigActionException::class);
|
||||
$this->expectExceptionMessage("The entity type for the config name 'node.\${anything}.test' could not be identified.");
|
||||
RecipeRunner::processRecipe($recipe);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ recipes:
|
|||
# Depend on another recipe in order to prove that we can collect input
|
||||
# from recipes that depend on other recipes.
|
||||
- no_extensions
|
||||
install:
|
||||
- node
|
||||
input:
|
||||
owner:
|
||||
data_type: string
|
||||
|
@ -27,8 +29,17 @@ input:
|
|||
default:
|
||||
source: value
|
||||
value: false
|
||||
node_type:
|
||||
data_type: string
|
||||
description: 'The ID of a node type to create'
|
||||
default:
|
||||
source: value
|
||||
value: 'test'
|
||||
config:
|
||||
actions:
|
||||
node.type.${node_type}:
|
||||
createIfNotExists:
|
||||
name: Test Content Type
|
||||
system.site:
|
||||
simpleConfigUpdate:
|
||||
name: "${owner}'s Turf"
|
||||
|
|
Loading…
Reference in New Issue