EntityField::getValue method has unexpected behavior for multivalue fields

Created on 8 October 2024, 2 months ago

Problem/Motivation

Drupal\views\Plugin\views\field\EntityField::getValue method returns in some particular situation values from multiple rows, not just from that one, that is sent to the method as the first argument.

It happens even when "group_rows" setting is set to FALSE.

The documentation of Drupal\views\Plugin\views\field\FieldHandlerInterface::getValue method is not clear about it, but I think, it is supposed to return the values just from the given views row.

Steps to reproduce

  1. Create view, that shows entity fields
  2. Add some multivalue field to the Fields section
  3. Let "Display all values in the same row" option unchecked in "Multiple field settings" fieldset
  4. Save the view
  5. Execute view programatically, and use Drupal\views\Plugin\views\field\FieldHandlerInterface::getValue method for getting results
  6. Method returns all field values grouped by entity, where field values are separated with comma as one field value. Unchecking of "Display all values in the same row" does not work.

The problem happens only when View results are gained programatically with mentioned method.

Proposed resolution

Would it be possible to adjust mentioned getValue method in that way, so the data would be gained from $row variable from method argument, instead from $row->_entity property?

Feature request
Status

Active

Version

11.0 🔥

Component

views.module

Created by

🇸🇰Slovakia tomas.teicher

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

Merge Requests

Comments & Activities

  • Issue created by @tomas.teicher
  • 🇳🇱Netherlands Lendude Amsterdam

    If you look at the code in \Drupal\views\Plugin\views\field\EntityField::getValue you can see that there is some extra logic needed to get the correct value, mainly getting the right translation for the requested data. So we can't just grab the value from the row, because that would lead to unexpected values being shown.

    Bu, yeah, the docs on that are a bit unclear as to the exact purpose of this method. But I don't think we can really change the way it works without breaking a lot of other things.

  • 🇸🇰Slovakia tomas.teicher

    Could be added some new method then?

    There is an use case for getting values from particular Views row programatically.

    The patch provided at that issue contains source code, that calls this method (indirectly).

    Maybe there can be a new public method like i.e. Drupal\views\Plugin\views\field\FieldHandlerInterface::getRowValue that would quarantee, that result contains just values from particular row?

  • First commit to issue fork.
  • Pipeline finished with Failed
    about 2 months ago
    Total: 191s
    #318037
  • Pipeline finished with Failed
    about 2 months ago
    Total: 186s
    #318047
  • 🇮🇳India KumudB Ahmedabad

    This patch addresses the issue where the `getValue()` method in Views returns values from multiple rows, even when it should only return values for a single row.

    Steps to reproduce:
    1. Create a view that shows entity fields.
    2. Add a multi-value field and ensure the "Display all values in the same row" option is unchecked.
    3. Programmatically execute the view and use the `getValue()` method to retrieve field values.

    Expected behavior: The field values should only display for the given row.
    Patch solution: Adjusted the `getValue()` method to fetch data directly from the passed `$row` argument rather than `$row->_entity`.

    Test instructions:

    - Create a view with a multi-value field and verify that only values for a specific row are returned.

    MR is created
    https://git.drupalcode.org/project/drupal/-/merge_requests/9914

  • Pipeline finished with Failed
    about 2 months ago
    Total: 156s
    #318055
  • 🇮🇳India KumudB Ahmedabad
    core/modules/views/src/Plugin/views/field/EntityField.php
    
    /**
       * {@inheritdoc}
       */
      public function getValue(ResultRow $values, $field = NULL) {
        // Ensure that we're getting the specific entity for the current row.
        $entity = $this->getEntity($values);
    
        // Ensure the object is not NULL before attempting to translate it.
        if ($entity === NULL) {
          return NULL;
        }
        // Retrieve the translated object for this specific row.
        $translated_entity = $this->getEntityFieldRenderer()->getEntityTranslationByRelationship($entity, $values);
    
        // Fetch the field items for the current entity's row.
        $field_item_list = $translated_entity->{$this->definition['field_name']} ?? NULL;
    
        if ($field_item_list === NULL) {
          // There isn't anything we can do without a valid field.
          return NULL;
        }
    
        $field_item_definition = $field_item_list->getFieldDefinition();
    
        $values = [];
        foreach ($field_item_list as $field_item) {
          /** @var \Drupal\Core\Field\FieldItemInterface $field_item */
          if ($field) {
            $values[] = $field_item->$field;
          }
          // Find the value using the main property of the field.
          elseif ($main_property_name = $field_item->mainPropertyName()) {
            $values[] = $field_item->{$main_property_name};
          }
          else {
            // Default to using the 'value' property.
            $values[] = $field_item->value;
          }
        }
        // Ensure the field is handled based on its cardinality.
        if ($field_item_definition->getFieldStorageDefinition()->getCardinality() == 1) {
          // Single cardinality field should return a single value.
          return reset($values);
        }
        else {
          // Multi-value field handling.
          // Check if grouping is enabled or not.
          if ($this->options['group_rows'] === FALSE) {
            // If grouping is disabled, return individual values.
            return $values;
          }
          else {
            // If grouping is enabled, return the values as a concatenated string.
            return implode(', ', $values);
          }
        }
      }

    This is the code and its working for me please review it.

  • 🇳🇿New Zealand quietone

    Changes are made on on 11.x (our main development branch) first, and are then back ported as needed according to our policies.

  • 🇳🇿New Zealand quietone

    Select the correct version this time.

Production build 0.71.5 2024