Pass block context to commerce_cart_block

Created on 5 November 2024, about 1 month ago

Problem/Motivation

Drupal blocks can be used more than once on a page. They contain content, that might need to be aware of this placement (context) to differ accordingly.

Theme commerce_cart_block (commerce_cart_block.html.twig) is used as content within the commerce_cart block (CartBlock.php).

The following parameters are passed:

    return [
      '#attached' => [
        'library' => ['commerce_cart/cart_block'],
      ],
      '#theme' => 'commerce_cart_block',
      '#icon' => [
        '#theme' => 'image',
        '#uri' => $this->moduleExtensionList->getPath('commerce') . '/icons/ffffff/cart.png',
        '#alt' => $this->t('Shopping cart'),
      ],
      '#count' => $count,
      '#count_text' => $this->formatPlural($count, '@count item', '@count items'),
      '#url' => Url::fromRoute('commerce_cart.page')->toString(),
      '#content' => $cart_views,
      '#links' => $links,
      '#cache' => [
        'contexts' => ['cart'],
      ],
      '#dropdown' => $this->configuration['dropdown'],
    ];

so it's currently not aware of its cart block context and can't vary on different placements.
For example, in our current project we need a cart block in the header and one in the mobile flyout that need different markup.

The additional variable would then also allow to optionally implement different theme hook suggestions, which is currently impossible.

This is higly related to Add a "context" array variable to all theme hooks and "#context" array property to all elements to provide optional contextual data Needs work but as it seems, this is stuck since years (still it makes a lot of sense)!

Steps to reproduce

Try to get the different context commerce_cart_block.html.twig is rendered in and see it's not possible.

Proposed resolution

Pass a #context variable to commerce_cart_block containing the block context.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Feature request
Status

Active

Version

3.0

Component

Cart

Created by

🇩🇪Germany Anybody Porta Westfalica

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @Anybody
  • 🇩🇪Germany Anybody Porta Westfalica

    (PS: I think this is the only case where this is needed and makes sense in commerce currently.)

  • 🇮🇱Israel jsacksick

    hm... I'm unclear on how you'd be passing the context array? Do you have code for embedding the block?
    What is preventing you from overridding CartBlock::build() with your own logic?
    Or can't a hook_preprocess_HOOK() help here? Not sure exactly why a change in Commerce core would be required for this? Since you have your own custom logic / usecase to support, it kind of makes sense to override the logic you need from your own codebase?

  • 🇩🇪Germany Anybody Porta Westfalica

    Thanks for the quick reply @jsacksick!

    So you suggest for example adding a custom cart block that extends the Commerce CartBlock and overrides build()?
    That's not a bad strategy, thank you! I didn't think about that!

    hook_preprocess_HOOK() doesn't help in this case, I think, if we're both talking about preprocessing commerce_cart_block, e.g.

    hook_preprocess_commerce_cart_block($variables) {
      ...
    }
    

    as there's no information about the context / block in there.

    But creating a simple custom extending block is a genius idea! We could still proceed here, providing context information, if the core issue is fixed, but I think it's not worth to wait for it. The benefit then would be having the context information available in twig without writing such custom code.

    Thank you!!

  • 🇮🇱Israel jsacksick

    I don't think you have to define a custom block, that's one way to do it but you can also swap the block class with your own.

    Using a hook_block_alter().
    function hook_block_alter(&$definitions) {

    You can set your own class like the following:
    $definitions['commerce_cart']['class'] = MyCartBlock::class;

  • 🇩🇪Germany Anybody Porta Westfalica

    Thanks @jsacksick! Extending the class with a custom block seems even more flexible and clearer!
    Your advice helped a lot!

Production build 0.71.5 2024