You are here

protected function SearchApiFieldTrait::extractPropertyValues in Search API 8

Places extracted property values and objects into the result row.

Parameters

\Drupal\views\ResultRow[] $values: The Views result rows from which property values should be extracted.

string $combined_property_path: The combined property path of the property to extract.

\Drupal\Core\TypedData\TypedDataInterface[][] $property_values: The values of the property for each result row, keyed by result row index.

string[] $dependents: The actually required properties (as combined property paths) that depend on this property.

1 call to SearchApiFieldTrait::extractPropertyValues()
SearchApiFieldTrait::preRender in src/Plugin/views/field/SearchApiFieldTrait.php
Runs before any fields are rendered.

File

src/Plugin/views/field/SearchApiFieldTrait.php, line 837

Class

SearchApiFieldTrait
Provides a trait to use for Search API Views field handlers.

Namespace

Drupal\search_api\Plugin\views\field

Code

protected function extractPropertyValues(array $values, $combined_property_path, array $property_values, array $dependents) {

  // Now go through the rows a second time and actually add all objects
  // and (if necessary) properties.
  foreach ($values as $i => $row) {
    if (!empty($property_values[$i])) {

      // Add the typed data for the property to our relationship objects
      // for this property path.
      $row->_relationship_objects[$combined_property_path] = [];
      foreach ($property_values[$i] as $j => $typed_data) {

        // If the typed data is an entity, check whether the current
        // user can access it (and switch to the right translation, if
        // available).
        $value = $typed_data
          ->getValue();
        if ($value instanceof EntityInterface) {
          if (!$this
            ->checkEntityAccess($value, $combined_property_path)) {
            continue;
          }
          if ($value instanceof TranslatableInterface && $value
            ->hasTranslation($row->search_api_language)) {

            // PhpStorm isn't able to keep both interfaces in mind at the same
            // time, so we need to use a third interface here that combines
            // both.

            /** @var \Drupal\Core\Entity\ContentEntityInterface $value */
            $typed_data = $value
              ->getTranslation($row->search_api_language)
              ->getTypedData();
          }
        }

        // To treat list properties correctly regarding possible child
        // properties, add all the list items individually.
        if ($typed_data instanceof ListInterface) {
          foreach ($typed_data as $item) {
            $row->_relationship_objects[$combined_property_path][] = $item;
            $row->_relationship_parent_indices[$combined_property_path][] = $j;
          }
        }
        else {
          $row->_relationship_objects[$combined_property_path][] = $typed_data;
          $row->_relationship_parent_indices[$combined_property_path][] = $j;
        }
      }
    }

    // Determine whether we want to set field values for this property on this
    // row. This is the case if the property is one of the explicitly
    // retrieved properties and not yet set on the result row object. Also, if
    // we have no objects for this property, we needn't bother anyways, of
    // course.
    if (!in_array($combined_property_path, $dependents) || isset($row->{$combined_property_path}) || empty($row->_relationship_objects[$combined_property_path])) {
      continue;
    }
    $row->{$combined_property_path} = [];

    // Iterate over the typed data objects, extract their values and set
    // the relationship objects for the next iteration of the outer loop
    // over properties.
    foreach ($row->_relationship_objects[$combined_property_path] as $typed_data) {
      $row->{$combined_property_path}[] = $this
        ->getFieldsHelper()
        ->extractFieldValues($typed_data);
    }

    // If we just set any field values on the result row, clean them up
    // by merging them together (currently it's an array of arrays, but
    // it should be just a flat array).
    if ($row->{$combined_property_path}) {
      $row->{$combined_property_path} = call_user_func_array('array_merge', $row->{$combined_property_path});
    }
  }
}