Problem/Motivation
If you attempt to add an extra field (pseudo field) or an EVA field to a product variation, Drupal crashes as soon as you add the field to the layout. The error is:
Notice: Undefined index: default_formatter in Drupal\layout_builder\Plugin\Block\FieldBlock->defaultConfiguration() (line 222 of /var/www/html/web/core/modules/layout_builder/src/Plugin/Block/FieldBlock.php).
Steps to reproduce
Create an extra field:
/**
* Implements hook_entity_extra_field_info().
*/
function HOOK_entity_extra_field_info() {
$extra = [];
foreach (ProductVariationType::loadMultiple() as $bundle) {
$extra['commerce_product_variation'][$bundle->id()]['display']['specifications'] = [
'label' => t('Specifications'),
'description' => t('Rendered table with all variation fields.'),
'weight' => 0,
'visible' => TRUE,
];
}
return $extra;
}
/**
* Implements hook_ENTITY_TYPE_view_alter() for commerce_product_variation.
*/
function HOOK_commerce_product_variation_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
$view_mode = $display->getMode();
if ($view_mode != 'default') {
$build['specifications'] = [
// Render specifications.
'#markup' => 'foo',
];
}
}
Configure a product display (not product variation) and enter layout builder.
Add the extra field that appears in the Product Variations list.
See the error.
Proposed resolution
Layout builder has two BlockPlugins; 'FieldBlock' and 'ExtraFieldBlock'. The relevant difference is that ExtraFieldBlock does not make use a view_mode. The problem comes from commerce_product_block_alter which incorrectly checks the base_plugin_id.
/**
* Implements hook_block_alter().
*/
function commerce_product_block_alter(array &$info) {
if (\Drupal::moduleHandler()->moduleExists('layout_builder')) {
$base_plugin_id = 'field_block' . PluginBase::DERIVATIVE_SEPARATOR . 'commerce_product_variation' . PluginBase::DERIVATIVE_SEPARATOR;
foreach ($info as $block_plugin_id => $block_definition) {
if (strpos($block_plugin_id, $base_plugin_id) !== FALSE) {
$info[$block_plugin_id]['class'] = VariationFieldBlock::class;
}
}
}
}
For a field block the base form id is: field_block:commerce_product_variation:field_name. However for an extra field, the pattern is: extra_field_block:commerce_product_variation:field_name.
The following line causes the issue: if (strpos($block_plugin_id, $base_plugin_id) !== FALSE). That also triggers for extra fields, where it should not. Instead the if-statement should check if the base plugin id starts with field_block. The logic should be: if (strpos($block_plugin_id, $base_plugin_id) === 0)
Remaining tasks
- Update the if-statement with above logic. This no longer triggers the error, but the fields are not getting replaced.
- Find out what fields need to get replaced; possibly a commerce product variation variant of ExtraFieldBlock?
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #2 | 3182636-2.patch | 777 bytes | richgerdes |
Issue fork commerce-3182636
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
richgerdesI ran into this issue using the AddToAny module with commerce. It took a bit to track down, but commerce is absolutely over targeting here.
I rolled a patch for @Neograph734's change. It works for me.
Comment #3
jsacksick commentedSo @Neograph734, could you describe what wasn't working with your proposed fix?
Comment #4
neograph734I cannot exactly recall anymore.
I think the core issue #3186711: Extra field placeholder are not replaced if they are not of the viewed entity better explains it. Layout builder is using big pipe or something to do a just-in-time replacement of a placeholder for all these extra fields. This works fine if these fields belong to the current displayed entity, but commerce is doing some extra magic to include product variation fields on the product. This extra handling makes that pseudo fields of product variations are not getting replaced by layout builder and instead show nothing. (The error is gone though.)
It could be that richgerdes is using a field that is on the product instead of the product variation and therefor does show?
I have dug for hours through commerce and layout builder code and cannot even recall if I have solved it or not, if I got something to render it for sure would not update when changing the product variation on the add to cart form. In the end I ended up using layout templates with variables for product and variation fields. (Copying the layout builder template and including the right libraries made them behave the same).
Comment #5
ivanbarr commentedI encountered this issue when installing Canvas 1.2.0 with Drupal core 11.3.3. Patch #2 resolves it correctly. We will continue working on further improvements.
Comment #6
ivanbarr commentedComment #12
byrond commentedAnyone using D11, should be using 3.x, which I think still has this issue. I've created an MR to reroll the 2.x patch.
Comment #15
neograph734I have tried 3182636-extra-field-in-layout (MR648) yesterday and I can confirm that it solved the issue.
RTBC for me, but since I originally pointed in this direction, I am not sure if that is enough.
Thanks!
Comment #17
jsacksick commented