diff --git a/core/modules/views/config/schema/views.area.schema.yml b/core/modules/views/config/schema/views.area.schema.yml index 51042e9587..a17668a349 100644 --- a/core/modules/views/config/schema/views.area.schema.yml +++ b/core/modules/views/config/schema/views.area.schema.yml @@ -51,6 +51,17 @@ views.area.result: type: text label: 'The shown text of the result summary area' +views.area.result_plural: + type: views.area.result + label: 'Result plural' + mapping: + content_plural: + type: text + label: 'Text to use for the plural form' + plural_count_token: + type: text + label: 'Plural count token' + views.area.title: type: views_area label: 'Title' diff --git a/core/modules/views/src/Plugin/views/area/Result.php b/core/modules/views/src/Plugin/views/area/Result.php index 6405a9bf43..547fa405e7 100644 --- a/core/modules/views/src/Plugin/views/area/Result.php +++ b/core/modules/views/src/Plugin/views/area/Result.php @@ -3,6 +3,7 @@ namespace Drupal\views\Plugin\views\area; use Drupal\Component\Utility\Html; +use Drupal\Component\Utility\Xss; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\views\style\DefaultSummary; @@ -15,6 +16,20 @@ */ class Result extends AreaPluginBase { + /** + * Total number of results. + * + * @var int + */ + protected $total; + + /** + * The token replacements. + * + * @var array + */ + protected $replacements = []; + /** * {@inheritdoc} */ @@ -60,7 +75,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { * {@inheritdoc} */ public function query() { - if (str_contains($this->options['content'], '@total')) { + if (strpos($this->options['content'], '@total') !== FALSE || strpos($this->options['content'], '@format_total') !== FALSE) { $this->view->get_total_rows = TRUE; } } @@ -74,53 +89,60 @@ public function render($empty = FALSE) { return []; } $output = ''; + $this->calculateTotalAndReplacements(); $format = $this->options['content']; + // Send the output. + if (!empty($this->total) || !empty($this->options['empty'])) { + $output .= Xss::filterAdmin(str_replace(array_keys($this->replacements), array_values($this->replacements), $format)); + // Return as render array. + return [ + '#markup' => $output, + ]; + } + + return []; + } + + /** + * Calculate the replacement tokens. + */ + protected function calculateTotalAndReplacements() { // Calculate the page totals. $current_page = (int) $this->view->getCurrentPage() + 1; $per_page = (int) $this->view->getItemsPerPage(); // @TODO: Maybe use a possible is views empty functionality. // Not every view has total_rows set, use view->result instead. - $total = $this->view->total_rows ?? count($this->view->result); + $this->total = $this->view->total_rows ?? count($this->view->result); $label = Html::escape($this->view->storage->label()); // If there is no result the "start" and "current_record_count" should be // equal to 0. To have the same calculation logic, we use a "start offset" // to handle all the cases. - $start_offset = empty($total) ? 0 : 1; + $start_offset = empty($this->total) ? 0 : 1; if ($per_page === 0) { $page_count = 1; $start = $start_offset; - $end = $total; + $end = $this->total; } else { - $page_count = (int) ceil($total / $per_page); + $page_count = (int) ceil($this->total / $per_page); $total_count = $current_page * $per_page; - if ($total_count > $total) { - $total_count = $total; + if ($total_count > $this->total) { + $total_count = $this->total; } $start = ($current_page - 1) * $per_page + $start_offset; $end = $total_count; } $current_record_count = ($end - $start) + $start_offset; // Get the search information. - $replacements = []; - $replacements['@start'] = $start; - $replacements['@end'] = $end; - $replacements['@total'] = $total; - $replacements['@label'] = $label; - $replacements['@per_page'] = $per_page; - $replacements['@current_page'] = $current_page; - $replacements['@current_record_count'] = $current_record_count; - $replacements['@page_count'] = $page_count; - // Send the output. - if (!empty($total) || !empty($this->options['empty'])) { - $output .= str_replace(array_keys($replacements), array_values($replacements), $format); - // Return as render array. - return [ - '#markup' => $output, - ]; - } - - return []; + $this->replacements['@start'] = $start; + $this->replacements['@end'] = $end; + $this->replacements['@total'] = $this->total; + $this->replacements['@format_total'] = number_format($this->total, 0, '.', ','); + $this->replacements['@label'] = $label; + $this->replacements['@per_page'] = $per_page; + $this->replacements['@current_page'] = $current_page; + $this->replacements['@current_record_count'] = $current_record_count; + $this->replacements['@page_count'] = $page_count; } } diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_area_result.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_area_result.yml index 05f574e59d..0e7ca44cbe 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_area_result.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_area_result.yml @@ -50,7 +50,7 @@ display: group_type: group admin_label: '' empty: true - content: "