views_merge_rows.module in Views Merge Rows 8
Same filename and directory in other branches
Registers View API information
File
views_merge_rows.moduleView source
<?php
/**
* @file
* Registers View API information
*/
use Drupal\views\ViewExecutable;
use Drupal\Core\Render\Element;
use Drupal\Core\Url;
/**
* Implements hook_theme().
*/
function views_merge_rows_theme($existing, $type, $theme, $path) {
$base = [
'render element' => 'form',
'path' => drupal_get_path('module', 'views_merge_rows') . '/templates',
];
return [
'merge_rows_theme' => $base + [
'template' => 'merge-rows-theme',
],
];
}
/**
* 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);
$extender = $view->display_handler
->getExtenders()['views_merge_rows'];
if (isset($extender)) {
$options = $extender
->get_options();
}
else {
$options = NULL;
}
if (!is_null($options) && $options['merge_rows'] && $items_per_page > 0) {
$view
->setItemsPerPage(0);
}
if (!is_null($options) && $options['merge_rows'] != FALSE) {
$view->style_plugin
->renderFields($view->result);
$rendered_fields = $view->style_plugin
->getRenderedFields();
$filters = [];
// 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 = [];
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 = [];
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':
case 'average':
case 'std_deviation':
$merged_row[$field_name] = [
$rendered_row[$field_name],
];
break;
case 'count':
$merged_row[$field_name] = 1;
break;
case 'filter':
case 'first_value':
case 'highest_value':
case 'lowest_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':
case 'average':
case 'std_deviation':
$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 = floatval((string) $rendered_row[$field_name]);
$merged_row_data = floatval((string) $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;
}
else {
views_merge_rows_unset_row($view, $row_index);
$merged_row_replaced = FALSE;
}
break;
case 'lowest_value':
// Strip the HTML from the rendered and merged fields data and grab
// the raw value.
$rendered_row_data = floatval((string) $rendered_row[$field_name]);
$merged_row_data = floatval((string) $merged_row[$field_name]);
if (!isset($first_value)) {
$first_value = TRUE;
}
// Place the lower value into the merged row array.
if ($first_value && !empty($rendered_row[$field_name])) {
$merged_row[$field_name] = $rendered_row[$field_name];
$merged_row_replaced = TRUE;
$first_value = FALSE;
}
elseif ($rendered_row_data <= $merged_row_data && !empty($rendered_row[$field_name])) {
$merged_row[$field_name] = $rendered_row[$field_name];
$merged_row_replaced = TRUE;
}
else {
views_merge_rows_unset_row($view, $row_index);
$merged_row_replaced = FALSE;
}
break;
}
}
switch ($field_config['merge_option']) {
case 'highest_value':
case 'lowest_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 = 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) {
views_merge_rows_unset_row($view, $row_index);
}
}
// 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 or lowest value from the view.
views_merge_rows_unset_row($view, $merge_row_index);
break;
}
$first_value = TRUE;
break;
default:
views_merge_rows_unset_row($view, $row_index);
$merged_rows[$merge_row_index] = $merged_row;
break;
}
}
}
// Store the merged rows back to the view's style plugin.
foreach ($merged_rows as $row_index => $merged_row) {
foreach ($options['field_config'] as $field_name => $field_config) {
switch ($field_config['merge_option']) {
case 'merge':
case 'merge_unique':
foreach ($merged_row[$field_name] as $field_index => $field_value) {
if (empty($field_value)) {
unset($merged_row[$field_name][$field_index]);
}
}
if ($field_config['exclude_first']) {
array_shift($merged_row[$field_name]);
}
$value_count = count($merged_row[$field_name]);
$i = 1;
foreach ($merged_row[$field_name] as $field_index => $field_value) {
if ($i != $value_count) {
$merged_row[$field_name][$field_index] = $field_config['prefix'] . $field_value . $field_config['separator'] . $field_config['suffix'];
}
else {
$merged_row[$field_name][$field_index] = $field_config['prefix'] . $field_value . $field_config['suffix'];
}
$i++;
}
unset($i);
unset($value_count);
$view->style_plugin
->setRenderedField(implode($merged_row[$field_name]), $row_index, $field_name);
break;
case 'sum':
case 'average':
case 'std_deviation':
$sum = 0;
if ($field_config['merge_option'] == 'average' || $field_config['merge_option'] == 'std_deviation') {
$sum_square = 0;
$count_field_values = 0;
}
$count_field_values = 0;
foreach ($merged_row[$field_name] as $field_index => $field_value) {
if (!empty($field_value)) {
$sum += floatval((string) $field_value);
if ($field_config['merge_option'] == 'std_deviation') {
$sum_square += floatval((string) $field_value) * floatval((string) $field_value);
}
$count_field_values++;
}
}
if ($field_config['merge_option'] == 'average' || $field_config['merge_option'] == 'std_deviation') {
$average = $sum / $count_field_values;
}
if ($field_config['merge_option'] == 'average') {
$sum = $average;
}
if ($field_config['merge_option'] == 'std_deviation') {
$average_square = $sum_square / $count_field_values;
if ($count_field_values = 1) {
$sum = 0;
}
else {
$sum = $count_field_values / ($count_field_values - 1) * ($average_square - $average * $average);
$sum = sqrt($sum);
}
}
$view->style_plugin
->setRenderedField($sum, $row_index, $field_name);
break;
case 'count_unique':
$view->style_plugin
->setRenderedField(count($merged_row[$field_name]), $row_index, $field_name);
break;
case 'count':
case 'filter':
case 'first_value':
case 'highest_value':
case 'lowest_value':
$view->style_plugin
->setRenderedField($merged_row[$field_name], $row_index, $field_name);
break;
case 'count_unique':
if ($field_config['exclude_first']) {
array_shift($merged_row[$field_name]);
}
$view->style_plugin
->setRenderedField(count($merged_row[$field_name]), $row_index, $field_name);
break;
}
}
}
}
}
/**
* Unsets the given row from the current display.
*
* @param object $view
* View object.
*
* @param int $row_index
* Supplied row index value.
*/
function views_merge_rows_unset_row(ViewExecutable $view, $row_index) {
unset($view->result[$row_index]);
--$view->total_rows;
}
/**
* Returns item per page for the current display.
*
* @param object $view
* View object.
*
* @return int $items_per_page
* Returns number of items per page set for the current display of the view.
*/
function get_items_per_page_for_current_display(ViewExecutable $view) {
$items_per_page = 0;
$uri = \Drupal::request()
->getRequestUri();
$uri_parts = parse_url($uri);
if (!empty($uri_parts['scheme'])) {
$currentURI = Url::fromUri(\Drupal::request()
->getRequestUri());
if (isset($currentURI['query']['items_per_page'])) {
$items_per_page = $currentURI['query']['items_per_page'];
}
}
elseif (isset($view->pager->options['items_per_page'])) {
$items_per_page = $view
->getItemsPerPage();
}
elseif (isset($view->pager->options['type']) && $view->pager->options['type'] == 'none') {
$items_per_page = 0;
}
else {
$items_per_page = $view
->getItemsPerPage();
}
return $items_per_page;
}
Functions
Name | Description |
---|---|
get_items_per_page_for_current_display | Returns item per page for the current display. |
views_merge_rows_theme | Implements hook_theme(). |
views_merge_rows_unset_row | Unsets the given row from the current display. |
views_merge_rows_views_pre_render | Implements hook_views_pre_render(). |