Skip to content
Snippets Groups Projects
Unverified Commit b436c8c9 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3503190 by phenaproxima, thejimbirch: Allow recipes to contain an...

Issue #3503190 by phenaproxima, thejimbirch: Allow recipes to contain an "extra" property with arbitrary information for specific modules to use

(cherry picked from commit c9212079)
parent 6ada4987
No related branches found
No related tags found
14 merge requests!12227Issue #3181946 by jonmcl, mglaman,!12079Issue #3523476 by matthiasm11: Add empty check on operator,!12024Fix: DocBlock comment for return value of Drupal\Core\Database\Connection::transactionManager(),!11974Draft: Issue #3495165 by catch, joeyroth, berdir, texas-bronius: Better warning...,!11934Issue #3520997: DefaultLazyPluginCollection unnecessarily instantiates plugins when sorting collection,!11887Issue #3520065: The migrate Row class API is incomplete,!11636Draft: Issue #3515643 by macsim: fieldNameExists method is inconsistent,!11515Issue #3480419 by mondrake, smustgrave, catch: Method...,!11380Issue #3490698 by catch, spokje: Bump MINIMUM_STABILITY back to 'stable' when...,!11281Use Drupal Core Leadership terminology in MAINTAINERS.txt,!11239Issue #3507548: Allow workspace changes listing to show all items, without a pager,!11238Fix issue #3051797,!11213Issue #3506743 by tomislav.matokovic: Increasing the color contrast for the navigation block title against the background of the navigation sidebar to at least 4.5:1,!11147Draft: Try to avoid manually setting required cache contexts
Pipeline #418793 canceled
Pipeline: drupal

#418795

    ......@@ -6,6 +6,7 @@
    use Drupal\Core\DefaultContent\Finder;
    use Drupal\Core\Extension\Dependency;
    use Drupal\Core\Extension\ExtensionDiscovery;
    use Drupal\Core\Extension\ModuleExtensionList;
    use Drupal\Core\Extension\ThemeExtensionList;
    use Drupal\Component\Serialization\Yaml;
    ......@@ -60,6 +61,8 @@ final class Recipe {
    * The default content finder.
    * @param string $path
    * The recipe's path.
    * @param array $extra
    * Any extra information to expose to specific modules.
    */
    public function __construct(
    public readonly string $name,
    ......@@ -71,6 +74,7 @@ public function __construct(
    public readonly InputConfigurator $input,
    public readonly Finder $content,
    public readonly string $path,
    private readonly array $extra,
    ) {}
    /**
    ......@@ -90,7 +94,7 @@ public static function createFromDirectory(string $path): static {
    $config = new ConfigConfigurator($recipe_data['config'], $path, \Drupal::service('config.storage'));
    $input = new InputConfigurator($recipe_data['input'] ?? [], $recipes, basename($path), \Drupal::typedDataManager());
    $content = new Finder($path . '/content');
    return new static($recipe_data['name'], $recipe_data['description'], $recipe_data['type'], $recipes, $install, $config, $input, $content, $path);
    return new static($recipe_data['name'], $recipe_data['description'], $recipe_data['type'], $recipes, $install, $config, $input, $content, $path, $recipe_data['extra'] ?? []);
    }
    /**
    ......@@ -296,6 +300,12 @@ private static function parse(string $file): array {
    'content' => new Optional([
    new Type('array'),
    ]),
    'extra' => new Optional([
    new Sequentially([
    new Type('associative_array'),
    new Callback(self::validateKeysAreValidExtensionNames(...)),
    ]),
    ]),
    ]);
    $recipe_data = Yaml::decode($recipe_contents);
    ......@@ -423,4 +433,40 @@ private static function validateConfigActions(mixed $value, ExecutionContextInte
    }
    }
    /**
    * Validates that the keys of an array are valid extension names.
    *
    * Note that the keys do not have to be the names of extensions that are
    * installed, or even extensions that exist. They just have to follow the
    * form of a valid extension name.
    *
    * @param array $value
    * The array being validated.
    * @param \Symfony\Component\Validator\Context\ExecutionContextInterface $context
    * The validator execution context.
    */
    private static function validateKeysAreValidExtensionNames(array $value, ExecutionContextInterface $context): void {
    $keys = array_keys($value);
    foreach ($keys as $key) {
    if (!preg_match(ExtensionDiscovery::PHP_FUNCTION_PATTERN, $key)) {
    $context->addViolation('%name is not a valid extension name.', [
    '%name' => $key,
    ]);
    }
    }
    }
    /**
    * Returns extra information to expose to a particular extension.
    *
    * @param string $extension_name
    * The name of a Drupal extension.
    *
    * @return mixed
    * The extra data exposed to the given extension, or NULL if there is none.
    */
    public function getExtra(string $extension_name): mixed {
    return $this->extra[$extension_name] ?? NULL;
    }
    }
    ......@@ -98,4 +98,19 @@ public function testImplicitlyRequiredModule(): void {
    $this->assertIsObject($recipe);
    }
    /**
    * Tests getting extra extension-specific info from a recipe.
    *
    * @covers ::getExtra
    */
    public function testExtra(): void {
    $recipe = $this->createRecipe([
    'name' => 'Getting extra info',
    'extra' => [
    'special_sauce' => 'Wasabi',
    ],
    ]);
    $this->assertSame('Wasabi', $recipe->getExtra('special_sauce'));
    }
    }
    ......@@ -719,6 +719,45 @@ public static function providerRecipeValidation(): iterable {
    default:
    source: config
    config: ['system.site', 'mail']
    YAML,
    NULL,
    ];
    yield 'extra is present and not an array' => [
    <<<YAML
    name: Bad extra
    extra: 'yes!'
    YAML,
    [
    '[extra]' => ['This value should be of type associative_array.'],
    ],
    ];
    yield 'extra is an indexed array' => [
    <<<YAML
    name: Bad extra
    extra:
    - one
    - two
    YAML,
    [
    '[extra]' => ['This value should be of type associative_array.'],
    ],
    ];
    yield 'invalid key in extra' => [
    <<<YAML
    name: Bad extra
    extra:
    'not a valid extension name': true
    YAML,
    [
    '[extra]' => ['not a valid extension name is not a valid extension name.'],
    ],
    ];
    yield 'valid extra' => [
    <<<YAML
    name: Bad extra
    extra:
    project_browser:
    yes: sir
    YAML,
    NULL,
    ];
    ......
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Please register or to comment