Skip to content
Snippets Groups Projects

Issue #3439923 by alexpott, nedjo, bircher, immaculatexavier, tasc, sonfd,...

Closed Alex Pott requested to merge issue/drupal-3439923:3439923-add-recipes-api into 11.x

Issue #3439923 by alexpott, nedjo, bircher, immaculatexavier, tasc, sonfd, deviantintegral, thejimbirch, phenaproxima, franz, Wim Leers, narendraR, Rajab Natshah, srishtiiee, omkar.podey: Add recipes API to core

Closes #3439923

Merge request reports

Loading
Loading

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
27 * @param \Drupal\Core\Config\ConfigManagerInterface $configManager
28 * The config manager.
29 * @param \Drupal\Core\Config\Action\Exists $exists
30 * Determines behavior of action depending on entity existence.
31 */
32 public function __construct(
33 protected readonly ConfigManagerInterface $configManager,
34 protected readonly Exists $exists
35 ) {
36 }
37
38 /**
39 * {@inheritdoc}
40 */
41 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
42 assert(is_array($plugin_definition) && is_array($plugin_definition['constructor_args']), '$plugin_definition contains the expected settings');
  • Tossing up whether we should assert the expected keys too/data-types but I think if you pass something other than the typed args and it blows up you get a clear indication of what you did wrong, so I think this is enough

  • Please register or sign in to reply
  • 58 }
    59
    60 $entity_type_manager = $this->configManager->getEntityTypeManager();
    61 $entity_type_id = $this->configManager->getEntityTypeIdByName($configName);
    62 if ($entity_type_id === NULL) {
    63 throw new ConfigActionException(sprintf("Cannot determine a config entity type from %s", $configName));
    64 }
    65 /** @var \Drupal\Core\Config\Entity\ConfigEntityTypeInterface $entity_type */
    66 $entity_type = $entity_type_manager->getDefinition($entity_type_id);
    67
    68 $id = substr($configName, strlen($entity_type->getConfigPrefix()) + 1);
    69 $entity_type_manager
    70 ->getStorage($entity_type->id())
    71 ->create($value + ['id' => $id])
    72 ->save();
    73 }
  • 80 ...$plugin_definition['constructor_args']
    81 );
    82 }
    83
    84 /**
    85 * {@inheritdoc}
    86 */
    87 public function apply(string $configName, mixed $value): void {
    88 /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface|null $entity */
    89 $entity = $this->configManager->loadConfigEntityByName($configName);
    90 if ($this->exists->returnEarly($configName, $entity)) {
    91 return;
    92 }
    93
    94 $entity = $this->pluralized ? $this->applyPluralized($entity, $value) : $this->applySingle($entity, $value);
    95 $entity->save();
  • 32 }
    33
    34 /**
    35 * {@inheritdoc}
    36 */
    37 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
    38 return new static($container->get('config.factory'));
    39 }
    40
    41 /**
    42 * {@inheritdoc}
    43 */
    44 public function apply(string $configName, mixed $value): void {
    45 $config = $this->configFactory->getEditable($configName);
    46 // @todo https://www.drupal.org/i/3439713 Should we error if this is a
    47 // config entity?
  • Lee Rowlands
  • 100 * The configuration name.
    101 * @param mixed $data
    102 * The data for the action.
    103 *
    104 * @throws \Drupal\Component\Plugin\Exception\PluginException
    105 * Thrown when the config action cannot be found.
    106 * @throws \Drupal\Core\Config\Action\ConfigActionException
    107 * Thrown when the config action fails to apply.
    108 */
    109 public function applyAction(string $action_id, string $configName, mixed $data): void {
    110 if (!$this->hasDefinition($action_id)) {
    111 // Get the full plugin ID from the shorthand map, if it is available.
    112 $entity_type = $this->configManager->getEntityTypeIdByName($configName);
    113 if ($entity_type) {
    114 $action_id = $this->getShorthandActionIdsForEntityType($entity_type)[$action_id] ?? $action_id;
    115 }
    • Comment on lines +113 to +115

      should we then check ::hasDefinition again or is it fine to let this throw at this point?

    • Author Maintainer

      I think this is fine because the exception from \Drupal\Component\Plugin\PluginManagerBase::createInstance() is a good one and will clearly point to a missing plugin.

    • Please register or sign in to reply
  • 118 $action = $this->createInstance($action_id);
    119 foreach ($this->getConfigNamesMatchingExpression($configName) as $name) {
    120 $action->apply($name, $data);
    121 $typed_config = $this->typedConfig->createFromNameAndData($name, $this->configFactory->get($name)->getRawData());
    122 // All config objects are mappings.
    123 assert($typed_config instanceof Mapping);
    124 foreach ($typed_config->getConstraints() as $constraint) {
    125 // Only validate the config if it has explicitly been marked as being
    126 // validatable.
    127 if ($constraint instanceof FullyValidatableConstraint) {
    128 /** @var \Symfony\Component\Validator\ConstraintViolationList $violations */
    129 $violations = $typed_config->validate();
    130 if (count($violations) > 0) {
    131 throw new InvalidConfigException($violations, $typed_config);
    132 }
    133 break;
    • Comment on lines +124 to +133

      This is where we validate :thumbsup: But if the action is calling :save are we too late? I assume this is where config checkpoints come in, note to self to confirm

    • Yep, that's the case! If validation fails, we revert the applies recipe thanks to the checkpoint just prior to the recipe application process starting :blush:

    • Please register or sign in to reply
  • Lee Rowlands
  • 188
    189 /**
    190 * Gets a map of shorthand action IDs to plugin IDs for an entity type.
    191 *
    192 * @param string $entityType
    193 * The entity type ID to get the map for.
    194 *
    195 * @return string[]
    196 * An array of plugin IDs keyed by shorthand action ID for the provided
    197 * entity type.
    198 */
    199 protected function getShorthandActionIdsForEntityType(string $entityType): array {
    200 $map = [];
    201 foreach ($this->getDefinitions() as $plugin_id => $definition) {
    202 if (in_array($entityType, $definition['entity_types'], TRUE) || in_array('*', $definition['entity_types'], TRUE)) {
    203 $regex = '/' . PluginBase::DERIVATIVE_SEPARATOR . '([^' . PluginBase::DERIVATIVE_SEPARATOR . ']*)$/';
  • Lee Rowlands
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Please register or sign in to reply
    Loading