class ComplexGrouping in Views Complex Grouping 8
Class ComplexGrouping.
Plugin annotation
@ViewsStyle(
id = "complex_grouping",
title = @Translation("Complex Grouping"),
help = @Translation("Limit the number of rows under each grouping field"),
theme = "views_view_complex_grouping_leave",
display_types = { "normal" }
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\views\Plugin\views\PluginBase implements DependentPluginInterface, ContainerFactoryPluginInterface, TrustedCallbackInterface, ViewsPluginInterface
- class \Drupal\views\Plugin\views\style\StylePluginBase
- class \Drupal\views_complex_grouping\Plugin\views\style\ComplexGrouping
- class \Drupal\views\Plugin\views\style\StylePluginBase
- class \Drupal\views\Plugin\views\PluginBase implements DependentPluginInterface, ContainerFactoryPluginInterface, TrustedCallbackInterface, ViewsPluginInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of ComplexGrouping
File
- src/
Plugin/ views/ style/ ComplexGrouping.php, line 21
Namespace
Drupal\views_complex_grouping\Plugin\views\styleView source
class ComplexGrouping extends StylePluginBase {
/**
* Whether or not this style uses a row plugin.
*
* @var bool
*/
protected $usesRowPlugin = TRUE;
/**
* Does the style plugin support grouping of rows.
*
* @var bool
*/
protected $usesGrouping = TRUE;
/**
* Denotes whether the plugin has an additional options form.
*
* @var bool
*/
protected $usesOptions = TRUE;
/**
* Does the style plugin for itself support to add fields to its output.
*
* This option only makes sense on style plugins without row plugins, like
* for example table.
*
* @var bool
*/
protected $usesFields = TRUE;
/**
* Name of the template used render.
*
* @var string
*/
protected $complexGroupingTheme = 'views_view_complex_grouping_level';
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$field_labels = $this->displayHandler
->getFieldLabels(TRUE);
foreach ($form['grouping'] as $index => $info) {
$form['grouping'][$index]['complex_grouping'] = [
'#type' => 'fieldset',
'#title' => t('Limit and extra fields for grouping field No. @num', [
'@num' => $index + 1,
]),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
];
$form['grouping'][$index]['complex_grouping']['grouping_fields'] = [
'#type' => 'select',
'#multiple' => TRUE,
'#title' => t('Selected'),
'#options' => $field_labels,
'#default_value' => $this
->getGroupingDefaultValues($index, 'grouping_fields'),
'#description' => t('Select which fields will be displayed alongside the field No. @num', [
'@num' => $index + 1,
]),
];
$form['grouping'][$index]['complex_grouping']['grouping_limit'] = [
'#type' => 'textfield',
'#title' => t('Items to display:'),
'#default_value' => $this
->getGroupingDefaultValues($index, 'grouping_limit'),
'#size' => 6,
'#element_validate' => [
[
get_called_class(),
'complexGroupingValidate',
],
],
'#description' => t('The number of rows to show under the field Nr. @num. Leave 0 to show all of them.', [
'@num' => $index + 1,
]),
];
$form['grouping'][$index]['complex_grouping']['grouping_offset'] = [
'#type' => 'textfield',
'#title' => t('Offset:'),
'#default_value' => $this
->getGroupingDefaultValues($index, 'grouping_offset'),
'#size' => 6,
'#element_validate' => [
[
get_called_class(),
'complexGroupingValidate',
],
],
'#description' => t('The row to start on.'),
];
}
}
/**
* Get default value for complex grouping options.
*/
private function getGroupingDefaultValues($index, $key) {
$default_option = NULL;
$options = $this->options['grouping'];
switch ($key) {
case 'grouping_limit':
$default_value = 0;
break;
case 'grouping_offset':
$default_value = 0;
break;
case 'grouping_fields':
default:
$default_value = NULL;
break;
}
$default_option = isset($options[$index]) ? $options[$index]['complex_grouping'][$key] ?: $default_value : $default_value;
return $default_option;
}
/**
* Group records as needed for rendering.
*/
public function renderGrouping($records, $groupings = [], $group_rendered = NULL) {
// This is for backward compatibility, when $groupings was a string
// containing the ID of a single field.
if (is_string($groupings)) {
$rendered = $group_rendered === NULL ? TRUE : $group_rendered;
$groupings = [
[
'field' => $groupings,
'rendered' => $rendered,
],
];
}
// Make sure fields are rendered.
$this
->renderFields($this->view->result);
$sets = [];
if ($groupings) {
foreach ($records as $index => $row) {
// Iterate through configured grouping fields to determine the
// hierarchically positioned set where the current row belongs to.
// While iterating, parent groups, that do not exist yet, are added.
$set =& $sets;
foreach ($groupings as $level => $info) {
$field = $info['field'];
$rendered = isset($info['rendered']) ? $info['rendered'] : $group_rendered;
$rendered_strip = isset($info['rendered_strip']) ? $info['rendered_strip'] : FALSE;
$grouping = '';
$group_content = '';
// Group on the rendered version of the field, not the raw. That way,
// we can control any special formatting of the grouping field through
// the admin or theme layer or anywhere else we'd like.
if (isset($this->view->field[$field])) {
$group_content = $this
->getField($index, $field);
if ($this->view->field[$field]->options['label']) {
$group_content = $this->view->field[$field]->options['label'] . ': ' . $group_content;
}
if ($rendered) {
$grouping = (string) $group_content;
if ($rendered_strip) {
$group_content = $grouping = strip_tags(htmlspecialchars_decode($group_content));
}
}
else {
$grouping = $this
->getFieldValue($index, $field);
// Not all field handlers return a scalar value,
// e.g. views_handler_field_field.
if (!is_scalar($grouping)) {
$grouping = hash('sha256', serialize($grouping));
}
}
}
// Create the group if it does not exist yet.
if (empty($set[$grouping])) {
$set[$grouping]['group'] = $group_content;
$set[$grouping]['level'] = $level;
$set[$grouping]['rows'] = [];
$set[$grouping]['fields'] = [];
// Add selected fields for this level.
foreach ($this->options['grouping'][$level]['complex_grouping']['grouping_fields'] as $field) {
$set[$grouping]['fields'][$field] = $this->rendered_fields[$index][$field];
}
}
// Move the set reference into the row set of the group
// we just determined.
$set =& $set[$grouping]['rows'];
}
// Add the row to the hierarchically positioned row set
// we just determined.
$set[$index] = $row;
}
}
else {
// If this parameter isn't explicitly set, modify the output to be fully
// backward compatible to code before Views 7.x-3.0-rc2.
// @TODO Remove this as soon as possible e.g. October 2020
if ($group_rendered === NULL) {
$old_style_sets = [];
foreach ($sets as $group) {
$old_style_sets[$group['group']] = $group['rows'];
}
$sets = $old_style_sets;
}
}
// Apply the offset and limit.
array_walk($sets, [
$this,
'complexGroupingRecursiveLimit',
]);
return $sets;
}
/**
* Render the grouping sets.
*/
public function renderGroupingSets($sets) {
$output = [];
$branch = 0;
$theme_functions = $this->view
->buildThemeFunctions($this->complexGroupingTheme);
foreach ($sets as $set) {
$branch++;
$level = isset($set['level']) ? $set['level'] : 0;
$row = reset($set['rows']);
// Render as a grouping set.
if (is_array($row) && isset($row['group'])) {
$single_output = [
'#theme' => $theme_functions,
'#view' => $this->view,
'#grouping' => $this->options['grouping'][$level],
'#grouping_branch' => $branch,
'#rows' => $set['rows'],
'#fields' => $set['fields'],
];
}
else {
if ($this
->usesRowPlugin()) {
foreach ($set['rows'] as $index => $row) {
$this->view->row_index = $index;
$set['rows'][$index] = $this->view->rowPlugin
->render($row);
}
}
$single_output = $this
->renderRowGroup($set['rows']);
$single_output['#grouping'] = $this->options['grouping'][$level];
$single_output['#grouping_branch'] = $branch;
$single_output['#fields'] = $set['fields'];
}
$single_output['#grouping_level'] = $level + 1;
$single_output['#title'] = $set['group'];
$output[] = $single_output;
}
unset($this->view->row_index);
return $output;
}
/**
* Recursively limits the number of rows in nested groups.
*/
protected function complexGroupingRecursiveLimit(array &$group_data, $key = NULL, $level = 1) {
$settings = $this
->complexGroupingSettings($level - 1);
$settings['grouping_limit'] = $settings['grouping_limit'] != 0 ? $settings['grouping_limit'] : NULL;
$settings['grouping_offset'] = isset($settings['grouping_offset']) ? $settings['grouping_offset'] : 0;
// Slice up the rows according to the offset and limit.
$group_data['rows'] = array_slice($group_data['rows'], $settings['grouping_offset'], $settings['grouping_limit'], TRUE);
// For each row, if it appears to be another grouping, recurse again.
foreach ($group_data['rows'] as &$data) {
if (is_array($data) && isset($data['group']) && isset($data['rows'])) {
$this
->complexGroupingRecursiveLimit($data, NULL, $level + 1);
}
}
}
/**
* Validate Complex Grouping form options.
*/
public static function complexGroupingValidate($element, FormStateInterface $form_state, $form) {
if (!is_numeric($element['#value'])) {
$form_state
->setError($element, t('%element must be numeric.', [
'%element' => $element['#title'],
]));
}
// Checking for negative val ues.
if ($element['#value'] < 0) {
$form_state
->setError($element, t('%element cannot be negative.', [
'%element' => $element['#title'],
]));
}
}
/**
* Helper function to retrieve settings for grouping limit.
*
* @param int $index
* The grouping level to fetch settings for.
*
* @return array
* Settings for this grouping level.
*/
protected function complexGroupingSettings($index) {
if ($this->options['grouping'][$index] && $this->options['grouping'][$index]['complex_grouping']) {
return $this->options['grouping'][$index]['complex_grouping'];
}
else {
return [
'grouping_limit' => 0,
'grouping_offset' => 0,
];
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ComplexGrouping:: |
protected | property | Name of the template used render. | |
ComplexGrouping:: |
protected | property |
Does the style plugin for itself support to add fields to its output. Overrides StylePluginBase:: |
|
ComplexGrouping:: |
protected | property |
Does the style plugin support grouping of rows. Overrides StylePluginBase:: |
|
ComplexGrouping:: |
protected | property |
Denotes whether the plugin has an additional options form. Overrides StylePluginBase:: |
|
ComplexGrouping:: |
protected | property |
Whether or not this style uses a row plugin. Overrides StylePluginBase:: |
|
ComplexGrouping:: |
public | function |
Provide a form to edit options for this plugin. Overrides StylePluginBase:: |
|
ComplexGrouping:: |
protected | function | Recursively limits the number of rows in nested groups. | |
ComplexGrouping:: |
protected | function | Helper function to retrieve settings for grouping limit. | |
ComplexGrouping:: |
public static | function | Validate Complex Grouping form options. | |
ComplexGrouping:: |
private | function | Get default value for complex grouping options. | |
ComplexGrouping:: |
public | function |
Group records as needed for rendering. Overrides StylePluginBase:: |
|
ComplexGrouping:: |
public | function |
Render the grouping sets. Overrides StylePluginBase:: |
|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
public | property | Plugins's definition | |
PluginBase:: |
public | property | The display object this plugin is for. | |
PluginBase:: |
public | property | Options for this plugin will be held here. | |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
protected | property | Stores the render API renderer. | 3 |
PluginBase:: |
public | property | The top object of a view. | 1 |
PluginBase:: |
public | function |
Calculates dependencies for the configured plugin. Overrides DependentPluginInterface:: |
14 |
PluginBase:: |
public static | function |
Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface:: |
62 |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
protected | function | Do the work to filter out stored options depending on the defined options. | |
PluginBase:: |
public | function |
Filter out stored options depending on the defined options. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public | function |
Returns an array of available token replacements. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function |
Returns the plugin provider. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
protected | function | Returns the render API renderer. | 1 |
PluginBase:: |
public | function |
Adds elements for available core tokens to a form. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public | function |
Returns a string with any core tokens replaced. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
constant | Include entity row languages when listing languages. | ||
PluginBase:: |
constant | Include negotiated languages when listing languages. | ||
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
PluginBase:: |
protected | function | Makes an array of languages, optionally including special languages. | |
PluginBase:: |
public | function |
Return the human readable name of the display. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public static | function |
Moves form elements into fieldsets for presentation purposes. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public static | function |
Flattens the structure of form elements. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public static | function | Returns substitutions for Views queries for languages. | |
PluginBase:: |
protected | function | Fills up the options of the plugin with defaults. | |
PluginBase:: |
public | function |
Handle any special handling on the validate form. Overrides ViewsPluginInterface:: |
16 |
PluginBase:: |
public | function |
Returns the summary of the settings in the display. Overrides ViewsPluginInterface:: |
6 |
PluginBase:: |
public | function |
Provide a full list of possible theme templates used by this style. Overrides ViewsPluginInterface:: |
1 |
PluginBase:: |
public | function |
Unpack options over our existing defaults, drilling down into arrays
so that defaults don't get totally blown away. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public | function |
Returns the usesOptions property. Overrides ViewsPluginInterface:: |
8 |
PluginBase:: |
protected | function | Replaces Views' tokens in a given string. The resulting string will be sanitized with Xss::filterAdmin. | 1 |
PluginBase:: |
constant | Query string to indicate the site default language. | ||
PluginBase:: |
public | function |
Constructs a PluginBase object. Overrides PluginBase:: |
|
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
StylePluginBase:: |
protected | property | Should field labels be enabled by default. | 1 |
StylePluginBase:: |
protected | property | The theme function used to render the grouping set. | |
StylePluginBase:: |
protected | property | Stores the rendered field values, keyed by the row index and field name. | |
StylePluginBase:: |
protected | property | Store all available tokens row rows. | |
StylePluginBase:: |
protected | property | Does the style plugin support custom css class for the rows. | 3 |
StylePluginBase:: |
public | function | Called by the view builder to see if this style handler wants to interfere with the sorts. If so it should build; if it returns any non-TRUE value, normal sorting will NOT be added to the query. | 1 |
StylePluginBase:: |
public | function | Called by the view builder to let the style build a second set of sorts that will come after any other sorts in the view. | 1 |
StylePluginBase:: |
public | function | Return TRUE if this style enables field labels by default. | 1 |
StylePluginBase:: |
protected | function |
Information about options for all kinds of purposes will be held here. Overrides PluginBase:: |
9 |
StylePluginBase:: |
public | function |
Clears a plugin. Overrides PluginBase:: |
|
StylePluginBase:: |
public | function | #pre_render callback for view row field rendering. | |
StylePluginBase:: |
public | function | Should the output of the style plugin be rendered even if it's a empty view. | 2 |
StylePluginBase:: |
public | function | Gets a rendered field. | |
StylePluginBase:: |
public | function | Get the raw field value. | |
StylePluginBase:: |
public | function | Return the token replaced row class for the specified row. | |
StylePluginBase:: |
public | function |
Overrides \Drupal\views\Plugin\views\PluginBase::init(). Overrides PluginBase:: |
|
StylePluginBase:: |
public | function | Allow the style to do stuff before each row is rendered. | |
StylePluginBase:: |
public | function |
Add anything to the query that we might need to. Overrides PluginBase:: |
1 |
StylePluginBase:: |
public | function | Render the display in this style. | 7 |
StylePluginBase:: |
protected | function | Renders all of the fields for a given style and store them on the object. | |
StylePluginBase:: |
protected | function | Renders a group of rows of the grouped view. | |
StylePluginBase:: |
public | function | Take a value and apply token replacement logic to it. | |
StylePluginBase:: |
public static | function |
Lists the trusted callbacks provided by the implementing class. Overrides PluginBase:: |
|
StylePluginBase:: |
public | function | Return TRUE if this style also uses fields. | 3 |
StylePluginBase:: |
public | function | Returns the usesGrouping property. | 3 |
StylePluginBase:: |
public | function | Returns the usesRowClass property. | 3 |
StylePluginBase:: |
public | function | Returns the usesRowPlugin property. | 10 |
StylePluginBase:: |
public | function | Return TRUE if this style uses tokens. | |
StylePluginBase:: |
public | function |
Validate that the plugin is correct and can be saved. Overrides PluginBase:: |
|
StylePluginBase:: |
public | function |
Validate the options form. Overrides PluginBase:: |
|
StylePluginBase:: |
public | function | Provide a form in the views wizard if this style is selected. | |
StylePluginBase:: |
public | function | Alter the options of a display before they are added to the view. | 1 |
TrustedCallbackInterface:: |
constant | Untrusted callbacks throw exceptions. | ||
TrustedCallbackInterface:: |
constant | Untrusted callbacks trigger silenced E_USER_DEPRECATION errors. | ||
TrustedCallbackInterface:: |
constant | Untrusted callbacks trigger E_USER_WARNING errors. |