Hi,
Thanks for this nice module.

It would be a very nice addition if there is support for Views arguments, just like these modules viewfield and viewsreference
they both work well also, but they only work for Views blocks.
Whereas I like the idea that your module can reference any block including the wonderful webform block.

Thanks for your work.

Comments

isamir created an issue. See original summary.

berdir’s picture

Title: Add support for Views arguments » Add support for block contexts (was: views arguments)
Version: 8.x-1.0-alpha4 » 8.x-1.x-dev
Status: Active » Needs review
Issue tags: -block field views arguments +Needs tests
StatusFileSize
new5.87 KB

I think the way to do this is plugin contexts. Views in Drupal 8.3 now exposes arguments in many but not all cases as contexts. Contexts that this module can display and pass to the block.

Here's a first patch that's working nicely for me.

Views arguments and context require some trickery, for example by using validation to accept node objects.

Steps to reproduce:

1. Create a new views block, list content. Add a contextual filter, content: ID, validate the argument to be Content, optionally of a certain bundle.
2. Add a block note that without this patch, the views block will not show up at all, with this patch it will.
3. Create content, it should now display

Note that this will not allow to pass in values that do not exist as context. For example for simple ids, strings or so. Similar to Page Manager, it would be possible for this module to allow to define user-provided, hardcoded context values, for example in the field settings, that would then be available for users to chose form.

Core currently only defines contexts for the current node and current user. The current node does allow quite a few use cases, you simply have to add another (reverse) relationship back to the node. For example, to show content that has the same tag in a certain field as the current node, you need to add a relationship to that field and then from there another relationship using that to content, then add a contextual filter on the Content: ID argument using the second relationship. Obviously the resulting views query will be.. suboptimal but it works. Improving that requires context relationships, e.g. being able to use the term id of the current node directly as context, ctools has some logic for that that we could optionally integrate?

Another issue is that views blocks are currently all optional, even if they were defined as required. That means the UI shows up and as a user, you have to explicitly select the context or it won't work.

PS:

While working on this, I noticed some things that might be worth looking at in other issues:

* Cacheability metadata of the access result is lost. This could be a security issue if blocks have strange access checks, resulting in blocks being visible when they shouldn't.
* BlockViewBuilder uses a lazy builder to actually render the block. If you have blocks that are not cacheable at all or are per-user, then the whole entity is uncacheable/per-user, a lazy builder would automatically be placeholdered and could be rendered later.

joelsteidl’s picture

Status: Needs review » Reviewed & tested by the community

I ran into this issue as well (Views with contextual filters were missing as available options) and this patch is working well with 8.x-1.0-alpha4. I tried with the dev version and got the WSOD.

cbeier’s picture

StatusFileSize
new144.29 KB

I have created a view block with a contextual filter based on a taxonomy term reference field. So I can get all nodes of a specific category.

My problem is, that the contextual filter form element has no options in the block field form.

Maybe it is better to use at this point a simple textfield to enter the contextual value manually (like Views preview).

yobottehg’s picture

Issue summary: View changes
Status: Reviewed & tested by the community » Needs work

I can confirm problems from #4. Does not work for an filter based on "News category" for example

berdir’s picture

Status: Needs work » Needs review

That is not a problem with this patch. This just allows to use existing contexts.

You can for example add another join to the view to join on the current node and then pass that as context, or write custom code to expose the category of the current node as a separate context.

There are tons of additional features possible on top of this, but those should be done in separate issues IMHO.

Still needs tests though.

joelsteidl’s picture

For clarity, this does not provide an open-ended input field for providing contextual info on the fly? I believe Views Reference Field works that way and I just wanted to check and make sure. It would be awesome to allow that sort of flexibility. An example of making a new context plugin would be cool to. Are there any good examples on D.O.?

Thanks!

ericb1021’s picture

StatusFileSize
new6.04 KB

After the last dev update, block-field-contexts-2862204-2.patch does not apply cleanly.

Updated patch attached.

opi’s picture

Not tested deeply, but patch from #8 works as expected in my use case (simple views block with contextual arguement). Thanks.

svdhout’s picture

This works great when using the patch in #8 combined with the oveo sandbox (https://www.drupal.org/project/oveo)

fenstrat’s picture

Looks good, thanks everyone! Would be great to get tests for this pretty please :)

Status: Needs review » Needs work

The last submitted patch, 8: block-field-contexts-2862204-8.patch, failed testing. View results

jody lynn’s picture

StatusFileSize
new5.74 KB

I rerolled the patch, but it didn't end up being useful to me due to the limitations described in 4 and 5

berdir’s picture

See #10, maybe oveo is useful for your use case?

berdir’s picture

Well, it doesn't help that the last two patches were rerolled incorrectly and the context is set too late :)

berdir’s picture

Status: Needs work » Needs review
marcoscano’s picture

Related issues: +#2976269: Sort block plugins alphabetically by label
StatusFileSize
new5.74 KB
new647 bytes

The patch in #15 removes the sorting of the definitions, so I'm adding it back here.

marcoscano’s picture

Issue tags: -Needs tests
StatusFileSize
new10.18 KB
new4.44 KB

Now with some test coverage added.

berdir’s picture

  1. +++ b/tests/src/Functional/WidgetTest.php
    @@ -64,13 +64,32 @@ class WidgetTest extends BrowserTestBase {
    +    $this->submitForm([
    +      'field_block[0][settings][context_mapping][nid]' => '@node.node_route_context:node',
    +      'field_block[0][settings][override][items_per_page]' => 10,
    +    ], $this->t('Save'));
    +    foreach ($items as $item) {
    

    Not quite sure why we have submitForm() and drupalPostForm().

    I guess alternatively we could also use the mink API directly with things like $page->fillField() + pressbutton(), that would allow us to use the actual labels of the form elements and assert that things are displayed correctly?

  2. +++ b/tests/src/Functional/WidgetTest.php
    @@ -64,13 +64,32 @@ class WidgetTest extends BrowserTestBase {
    +    }
    +    // The node we are visiting does not show up anymore.
    +    $first_result = $this->assertSession()->elementExists('css', '.view-items .view-content > .views-row:nth-child(1)');
    +    $this->assertNotEquals('Block field test', $first_result->getText());
    

    Negative tests are always tricky, lets make sure there's at least one additional node in the view being displayed?

marcoscano’s picture

StatusFileSize
new11.46 KB
new3.1 KB

@Berdir thanks for reviewing!

When modifying an existing test, I normally try to not modify it too much, so I just repeated what was already there... :)
But I agree that using mink's methods gives us more flexibility and actually makes it more readable. So I did that in this patch.

Thanks!

berdir’s picture

Status: Needs review » Needs work
+++ b/tests/src/Functional/WidgetTest.php
@@ -80,16 +93,17 @@ class WidgetTest extends BrowserTestBase {
+    $page->selectFieldOption('Exclude', '@node.node_route_context:node');

according to \Behat\Mink\Element\NodeElement::selectOption(), this should also work by selecting it with the label/text of the option.

  1. +++ b/src/BlockFieldManager.php
    @@ -17,33 +18,32 @@ class BlockFieldManager implements BlockFieldManagerInterface {
    -    return $block_definitions;
    +    // @todo Is this service still necessary?
    +    $definitions = $this->blockManager->getDefinitionsForContexts($this->contextRepository->getAvailableContexts());
    +    return $this->blockManager->getSortedDefinitions($definitions);
    

    I guess we can drop that @todo, still seems useful with the sorting.

  2. +++ b/src/Plugin/Field/FieldFormatter/BlockFieldFormatter.php
    @@ -30,6 +32,16 @@ class BlockFieldFormatter extends FormatterBase {
           if (!$block_instance || !$block_instance->access(\Drupal::currentUser())) {
             continue;
           }
    +      // Inject runtime contexts.
    +      if ($block_instance instanceof ContextAwarePluginInterface) {
    

    We should actually move this above access() as that might need the injected context as well.

    See \Drupal\ctools_block\Plugin\Block\EntityField::blockAccess() for example, which expects the context to be present when checking access.

  3. +++ b/src/Plugin/Field/FieldWidget/BlockFieldWidget.php
    @@ -269,6 +274,13 @@ class BlockFieldWidget extends WidgetBase implements ContainerFactoryPluginInter
    +        // If this block is context-aware, set the context mapping.
    +        // @todo Does not make sense that the form building is in BlockBase
    +        //   but this is not.
    +        if ($block instanceof ContextAwarePluginInterface && $block->getContextDefinitions()) {
    +          $context_mapping = $subform_state->getValue('context_mapping', []);
    +          $block->setContextMapping($context_mapping);
    

    It indeed doesn't but without any reference, the @todo isn't of much use :)

    I'd say change it from a WTF-todo a normal comment that just states this as a fact.

marcoscano’s picture

Status: Needs work » Needs review
StatusFileSize
new11.7 KB
new3.46 KB

@Berdir thanks for the feedback!

In the last point, I was honestly unable to decipher the meaning of that comment..., so I just dropped the @todo altogether. Please let me know if you think something else should be added instead.

  • fenstrat committed e7f2873 on 8.x-1.x authored by marcoscano
    Issue #2862204 by marcoscano, Berdir, EricB1021, Jody Lynn, cbeier: Add...
fenstrat’s picture

Status: Needs review » Fixed

This looks great, thanks everyone, committed!

Tests are good, I also manually tested. Agree with the removal of the `@todo`, if you feel it should be a comment @Berdir can you reopen with details on that.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

stefvanlooveren’s picture

Can't get this to work in Drupal 10.1. Am I missing something?
1) view > add contextual filter e.g. term reference
2) no options to manipulate/set the contextual filter in the block field

Goal is to manually set my contextual filter e.g. "Show teasers of content with tag X" where X is a value the webmaster can set.

berdir’s picture

You need to use Argument validation and have something that provides context.

This is not a filter to set manually. This is for context like current node/term.