Hi all,

I am quite new in module development even though I have a strong programming basis. I am currently porting a module to D8 I absolutely need for a client (Views Merge Rows) and I encountered a problem with $view->style_plugin->RenderFields($view->result).

My view used for tests purposes has 3 fields from 2 different content types. 1 of these field is the same in both content.

I do not understand why a call to $view->style_plugin->RenderFields($view->result) does not return any field so my pre_render function does not do what it should. Here is the code:

/**
 * Implements hook_views_pre_render().
 *
 * Merges the rows according to the settings for current display.
 */
function views_merge_rows_views_pre_render(ViewExecutable $view) {
  $items_per_page = get_items_per_page_for_current_display($view);
  $options = isset($view->display_handler->extenders['views_merge_rows']) ?
    $view->display_handler->extenders['views_merge_rows']->get_options() : NULL;
  if (!is_null($options) && $options['merge_rows'] && $items_per_page > 0) {
    $view->set_items_per_page(0);
  }
  $rendered_fields = $view->style_plugin->renderFields($view->result);
  $filters = array();

  // Array, where each element corresponds to the row after removing the merged
  // rows. This element is an array of fields (field_name is used as a key).
  // The values of this field depends on the merge_option as follows:
  // merge_unique - array of unique values from all merged rows
  // merge - array of values from all merger rows
  // filter - the value from the first merged rows (all values from the merged
  // rows are the same)
  // first_value - the value from the first merged rows
  // count_unique - array of unique values from all merged rows
  // count - the number of merged rows.
  $merged_rows = array();
  foreach ((array)$rendered_fields as $row_index => $rendered_row) {
    $filter_value = '';
    foreach ($options['field_config'] as $field_name => $field_config) {
      if ($field_config['merge_option'] == 'filter') {
        $filter_value .= $rendered_row[$field_name];
      }
    }
    if (!array_key_exists($filter_value, $filters)) {
      $merged_row_replaced = FALSE;
      $filters[$filter_value] = $row_index;
      $merged_row = array();
      foreach ($options['field_config'] as $field_name => $field_config) {
        switch ($field_config['merge_option']) {
          case 'count_unique':
            if (!in_array($rendered_row[$field_name], $merged_row[$field_name])) {
              $merged_row[$field_name][] = $rendered_row[$field_name];
            }
            break;
          case 'merge_unique':
          case 'merge':
          case 'sum':
            $merged_row[$field_name] = array($rendered_row[$field_name]);
            break;
          case 'count':
            $merged_row[$field_name] = 1;
            break;
          case 'filter':
          case 'first_value':
          case 'highest_value':
            $merged_row[$field_name] = $rendered_row[$field_name];
            break;

        }
      }
      $merged_rows[$row_index] = $merged_row;
    }
    else {
      $merge_row_index = $filters[$filter_value];
      $merged_row = $merged_rows[$merge_row_index];
      foreach ($options['field_config'] as $field_name => $field_config) {
        switch ($field_config['merge_option']) {
          case 'merge_unique':
          case 'count_unique':
            if (!empty($rendered_row[$field_name]) && !in_array($rendered_row[$field_name], $merged_row[$field_name])) {
               $merged_row[$field_name][] = $rendered_row[$field_name];
            }
            break;
          case 'merge':
          case 'sum':
            $merged_row[$field_name][] = $rendered_row[$field_name];
            break;
          case 'count':
            $merged_row[$field_name] = $merged_row[$field_name] + 1;
            break;
          case 'filter':
          case 'first_value':
            // Do nothing - we already have a value from the first merged row.
            break;
          case 'highest_value':
            // Strip the HTML from the rendered and merged fields data and grab
            // the raw value.
            $rendered_row_data = (int) strip_tags($rendered_row[$field_name]);
            $merged_row_data = (int) strip_tags($merged_row[$field_name]);

            // Place the higher value into the merged row array.
            if ($rendered_row_data > $merged_row_data) {
              $merged_row[$field_name] = $rendered_row[$field_name];
              $merged_row_replaced = TRUE;
            }
            // Remove the lower value row from the view.
            else {
              views_merge_rows_unset_row($view, $row_index);
              $merged_row_replaced = FALSE;
            }
            break;
        }
      }
      switch ($field_config['merge_option']) {
        case 'highest_value':
          // If we replaced the row with a higher value, then update all array
          // indexes with the new index values.
          if ($merged_row_replaced == TRUE) {
            $merged_rows[$row_index] = $merged_row;
            // Getting the items per page setting from the view display.
            /*$items_per_page = isset($view->display[$view->current_display]->display_options['pager']['options']['items_per_page']) ?
              $view->display[$view->current_display]->display_options['pager']['options']['items_per_page'] : 0;*/
            $items_per_page = get_items_per_page_for_current_display($view);
            $total_items = $view->total_rows;
            // Getting pager values as per merged rows.
            $merged_rows_total_num = count($merged_rows);

            if ($items_per_page > 0 && $merged_rows_total_num > $items_per_page) {

              $current_page_num = isset($view->query->pager->current_page) ? $view->query->pager->current_page : 0;
              $page_rows = $all_pages = 0;
              foreach ($merged_rows as $row_index => $merged_row) {
                if ($page_rows >= $items_per_page) {
                  $all_pages++;
                  $page_rows = 1;
                } else
                  $page_rows++;

                // Unsetting all results but the ones from current page.
                if ($all_pages != $current_page_num) {
                  unset($merged_rows[$row_index]);
                  unset($view->style_plugin->row_tokens[$row_index]);
                  unset($view->style_plugin->render_tokens[$row_index]);
                  unset($view->style_plugin->rendered_fields[$row_index]);
                  unset($view->result[$row_index]);
                  --$view->total_rows;
                }
              }
              // Attaching the pager with correct values.
              pager_default_initialize($merged_rows_total_num, $items_per_page);
            }
            $view->total_rows = $total_items;
            $filters[$filter_value] = $row_index;

            // Remove the previous highest value from the view.
            views_merge_rows_unset_row($view, $merge_row_index);
            break;
          }
          break;

        default:
          views_merge_rows_unset_row($view, $row_index);
          $merged_rows[$merge_row_index] = $merged_row;
          break;
      }
    }
  }

Did I miss something ? I've already made the function public. Your input will be greatly appreciated. Thanks.

Please note I intend to shorten the function when it will vork.

Comments

dgagne’s picture

I found the problem and open issues accordingly. This is due to a different implementation iof the function n D8 than it used to be in D7.