Problem/Motivation

ConditionPluginBase::buildConfiguration() depends on a form state item set by the parent form. This makes the form less portable, and although it may not be a violation of PluginFormInterface, it means that the plugins' forms are not as easy to embed as PluginFormInterface suggests.

Proposed resolution

Let ConditionPluginBase retrieve available contexts through the context.repository service itself if no contexts are stored in the form state. This also prevents problems when #2537732: PluginFormInterface must have access to the complete $form_state (introduce SubFormState for embedded forms) is committed, because it would prevent plugin forms from accessing the global form state, and thus the globally set contexts.
The only current usage of this global form state key is in BlockForm::form(), and that is equivalent to the proposed solution.

Remaining tasks

Allow the context repository to be optionally injected to ConditionBase plugins through the constructor, and add a protected ::getContextRepository() method that uses service location in case the context repository is not injected. This causes a minor break of unit tests of code that calls ConditionPluginBase::buildConfiguration(), because the context repository is not mocked in those tests yet.

User interface changes

None.

API changes

None.

Data model changes

Comments

Xano created an issue. See original summary.

xano’s picture

Issue summary: View changes
xano’s picture

Status: Active » Needs review
StatusFileSize
new4.19 KB

The original code that accessed the form state was a weird kind of integration between BlockForm and ConditionPluginBase. I'm not sure this is covered by any tests, as #2537732: PluginFormInterface must have access to the complete $form_state (introduce SubFormState for embedded forms) passes all tests, but the integration between these two classes should be broken. I'd love to be able to remove it completely, as this integration is very obscure, and we can alter ConditionPluginBase without breaking anything as long as no other code uses this form state value directly. If we can't, do we have conventions for testing such deprecated integrations?

xano’s picture

StatusFileSize
new707 bytes
new4.2 KB

The last submitted patch, 3: drupal_2647464_3.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 4: drupal_2647464_4.patch, failed testing.

xano’s picture

Status: Needs work » Needs review
StatusFileSize
new646 bytes
new4.2 KB
xano’s picture

StatusFileSize
new696 bytes
new4.61 KB

BlockForm::submitForm() sets context mapping values on context-aware condition plugins, but these values come from the condition plugin forms, which means the plugins must submit these values themselves, and they're none of BlockForm's business.

xano’s picture

StatusFileSize
new2.28 KB
new5.57 KB

I'm not enirely familiar with the context system, but it seems we'll want contexts to be set on conditions from outside through ::setContext() as well. This patch allows condition configuration forms to use contexts from three sources:

  1. Globally available contexts
  2. Contexts retrieved from the form state for backwards-compatibility with BlockForm, although we may want to remove that, as the retrieval of globally available conditions from within condition plugins replaces this integration.
  3. Individual contexts set on conditions using ::setContext().

Status: Needs review » Needs work

The last submitted patch, 9: drupal_2647464_9.patch, failed testing.

xano’s picture

The test fails, because the Language condition's context form is suddenly visible. What is the reason users are not supposed to configure this context?

dsnopek’s picture

I'm not enirely familiar with the context system, but it seems we'll want contexts to be set on conditions from outside through ::setContext() as well.

I'm not entirely familiar with this issue, but... :-) Plugins really shouldn't be directly accessing the ContextRepository. They should be dealing only with contexts passed to them via ::setContext(). Getting the contexts out of the ContextRepository and passing them to the plugin is the job of the thing using the plugin, and should never be done by a plugin itself.

This is important because the context repository is looking at stuff from the current request. If, for example, you're editing a page in Page Manager, you want to be able to set the contexts to the values that would be used on the page you are editing, not the page with the admin form on it.

That said, I'm not really familiar with this issue, so I might be misunderstanding something. Tim Plunkett and EclipseGC know the block and context systems much better than me, so input from them would be good!

tim.plunkett’s picture

+++ b/core/lib/Drupal/Core/Condition/ConditionPluginBase.php
@@ -52,8 +98,22 @@ public function isNegated() {
   public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
...
+    $contexts = $this->getContextRepository()->getAvailableContexts();

I'm sorry but this is severely wrong. Each plugin should NOT have the context repository. What about passing them in as a parameter?

Or just suck it up and won't fix.

xano’s picture

I'm sorry but this is severely wrong. Each plugin should NOT have the context repository. What about passing them in as a parameter?

That's what @EclipseGc and I settled on when discussing this on IRC.

Or just suck it up and won't fix.

That's not very productive. We should fix it either in D8, or postpone to D9. Let's try the former now we have an unexplored possible solution.

xano’s picture

Status: Needs work » Needs review
StatusFileSize
new6.89 KB

Let's try this. No interdiff, because it's a completely different approach.

Status: Needs review » Needs work

The last submitted patch, 15: drupal_2647464_15.patch, failed testing.

dsnopek’s picture

As far as contexts, #15 looks way better!

However, this adds an extra argument to a method on an existing interface, and I'm not sure how the core committers will see that as far as BC. I think this would make any class that implements ConditionInterface or BlockPluginInterface without extending the base classes cause a fatal error because it's missing the new argument? :-/

xano’s picture

It does not add any extra methods, as both interfaces already extend PluginFormInterface. The patch merely adds a third, optional parameter to an existing method, and therefore is fully backwards-compatible.

dsnopek’s picture

@Xano: Ah, ok, sorry! I thought adding an additional argument to a method on an interface (even an optional argument) would need to be implemented by implementors of the interface. Sorry for the noise!

berdir’s picture

@dsnopek is right. An optional method on an interface is *required* for implementing classes to be specified, a method definition must match an interface exactly.

Adding optional arguments only works for classes that are extending an interface, not the other way round.

I don't really understand how this arguments makes it really better, it's still something special that you have to know about? Just document that the specified key has to be provided in $form_state, problem solved?

xano’s picture

I don't really understand how this arguments makes it really better, it's still something special that you have to know about? Just document that the specified key has to be provided in $form_state, problem solved?

  1. Passing on required values through arbitrary key-value storage is not an API.
  2. The form state key not self-documenting.
  3. The form state key is global, which means it cannot be reused for different plugins in the same form.
eclipsegc’s picture

Well ok, so just answering the points here:

1.) Agreed it's not an API. But we shipped with it, so it might be our best option for the time being
2.) Which is exactly why berdir is suggesting we document it
3.) The available contexts are just as global as the form state which is exactly why I put it there. If every single condition plugin got this same group of gathered contexts, well that's ok because it's exactly what I intended. The plugin has no notion of its SPECIFIC configured context at this point, we are in fact getting all of them so that we can go through exactly that process.

While I'd love to clean this up in some way, there's a reason that it went down like you see it and it's essentially all of the same things you're struggling against right now.

Eclipse

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

andypost’s picture

This is the only issue left to close parent meta

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

andypost’s picture

Version: 9.5.x-dev » 10.1.x-dev

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.