The way OrderTotalSummary and OrderItemTable formatters build their renderable array is not compatible with inserting them into views.
Here are the steps to reproduce:
- Make sure you have at least some orders already generated in your store
- Create a new view on commerce order
- Add "Total price" field to the view and specify "order total summary" as its formatter
- Add "Order items" field to the view and specify "order item table" as its formatter
- Observe nothing output in those 2 fields when the view is executed.
Both just do a simple (no-children) renderable array:
\Drupal\commerce_order\Plugin\Field\FieldFormatter\OrderTotalSummary::viewElements():
public function viewElements(FieldItemListInterface $items, $langcode) {
$order = $items->getEntity();
return [
'#theme' => 'commerce_order_total_summary',
'#totals' => $this->orderTotalSummary->buildTotals($order),
];
}
\Drupal\commerce_order\Plugin\Field\FieldFormatter\OrderItemTable::viewElements():
public function viewElements(FieldItemListInterface $items, $langcode) {
$order = $items->getEntity();
return [
'#type' => 'view',
// @todo Allow the view to be configurable.
'#name' => 'commerce_order_item_table',
'#arguments' => [$order->id()],
'#embed' => TRUE,
];
}
Then the view runs the following code (in \Drupal\views\Plugin\views\field\EntityField::getItems()):
public function getItems(ResultRow $values) {
if (!$this->displayHandler->useGroupBy()) {
$build_list = $this->getEntityFieldRenderer()->render($values, $this);
}
else {
// For grouped results we need to retrieve a massaged entity having
// grouped field values to ensure that "grouped by" values, especially
// those with multiple cardinality work properly. See
// \Drupal\Tests\views\Kernel\QueryGroupByTest::testGroupByFieldWithCardinality.
$display = [
'type' => $this->options['type'],
'settings' => $this->options['settings'],
'label' => 'hidden',
];
// Optional relationships may not provide an entity at all. So we can't
// use createEntityForGroupBy() for those rows.
if ($entity = $this->getEntity($values)) {
$entity = $this->createEntityForGroupBy($entity, $values);
// Some bundles might not have a specific field, in which case the faked
// entity doesn't have it either.
$build_list = isset($entity->{$this->definition['field_name']}) ? $entity->{$this->definition['field_name']}->view($display) : NULL;
}
else {
$build_list = NULL;
}
}
// ---------------------
// --------------------- Here the $build_list is what the formatter has given us in its ::viewElements().
// ---------------------
if (!$build_list) {
return [];
}
if ($this->options['field_api_classes']) {
return [['rendered' => $this->renderer->render($build_list)]];
}
// ---------------------
// --------------------- The part below is the problem: here we expect the $build_list to be
// --------------------- indexed by deltas whereas the 2 formatters do not index them
// --------------------- that way.
// ---------------------
// Render using the formatted data itself.
$items = [];
// Each item is extracted and rendered separately, the top-level formatter
// render array itself is never rendered, so we extract its bubbleable
// metadata and add it to each child individually.
$bubbleable = BubbleableMetadata::createFromRenderArray($build_list);
foreach (Element::children($build_list) as $delta) {
BubbleableMetadata::createFromRenderArray($build_list[$delta])
->merge($bubbleable)
->applyTo($build_list[$delta]);
$items[$delta] = [
'rendered' => $build_list[$delta],
// Add the raw field items (for use in tokens).
'raw' => $build_list['#items'][$delta],
];
}
// ---------------------
// --------------------- Thus down here we wind up with empty $items.
// ---------------------
return $items;
}
Comments
Comment #2
bucefal91 commentedLooking at the docs to the
::viewElements()method (in\Drupal\Core\Field\FormatterInterface) we see:So the interface obliges its implementations to index the returned renderable array by deltas. That means the 2 formatters are the offending side in this views vs. formatters confrontation :)
I attach a patch that simply wraps the existing 2 formatters into this delta notion that is expected from them.
Comment #3
bucefal91 commentedI am not sure why it didn't want to queue my patch for testing, but I ran tests locally (including the JS ones) and have the following results (attached as a txt file).
Comment #4
sumanthkumarc commented@bucefal91 , the D.O issue queues are used for issue management and the github repo of commerce : https://github.com/drupalcommerce is used for PR. then the code is synced back. i guess there's some problme with drupal CI bot for commerce.
Comment #5
sumanthkumarc commentedfollow issue here: https://www.drupal.org/node/2855587 for CI bot, if you can help
Comment #6
bucefal91 commentedI see. Didn't know about that. Thanks for letting me know.
Here's the pull request https://github.com/drupalcommerce/commerce/pull/723 (I hope I did everything properly, it's my 1st pull request on git hub :) )
Comment #7
bojanz commentedLeft comments on the PR, don't see why we're introducing the if ($items->count() > 0) { check.
Comment #8
bojanz commentedThis got forgotten for a long time. Wrapping up.
Comment #10
bojanz commentedSorry for the delay!