From 5c55e45c3c02748d7e27349d476634096d0730f6 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 17 Feb 2021 16:09:38 +0100 Subject: [PATCH 1/9] Use splat operator instead of call_user_func_array --- models/GenericTable.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/models/GenericTable.php b/models/GenericTable.php index 8ce49f0..a06b8ef 100644 --- a/models/GenericTable.php +++ b/models/GenericTable.php @@ -37,7 +37,7 @@ class GenericTable extends PageIndex $this->tableIsSortable = !empty($options['base_url']); // How much stuff do we have? - $this->recordCount = call_user_func_array($options['get_count'], !empty($options['get_count_params']) ? $options['get_count_params'] : []); + $this->recordCount = $options['get_count'](...(!empty($options['get_count_params']) ? $options['get_count_params'] : [])); // Should we create a page index? $this->items_per_page = !empty($options['items_per_page']) ? $options['items_per_page'] : 30; @@ -60,7 +60,7 @@ class GenericTable extends PageIndex $parameters = array_merge($parameters, $options['get_data_params']); // Okay, let's fetch the data! - $data = call_user_func_array($options['get_data'], $parameters); + $data = $options['get_data'](...$parameters); // Clean up a bit. $rows = $data['rows']; @@ -150,7 +150,7 @@ class GenericTable extends PageIndex $parameters = [$column['parse']['data']['pattern']]; foreach ($column['parse']['data']['arguments'] as $identifier) $parameters[] = $row[$identifier]; - $value = call_user_func_array('sprintf', $parameters); + $value = sprintf(...$parameters); break; // timestamps: let's make them readable! From 96937b69523ceecd3176cb4ea3aacef0f2f7e971 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 17 Feb 2021 16:09:49 +0100 Subject: [PATCH 2/9] Use null-coalescing operator where appropriate --- models/GenericTable.php | 16 ++++++---------- templates/FormView.php | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/models/GenericTable.php b/models/GenericTable.php index a06b8ef..729d414 100644 --- a/models/GenericTable.php +++ b/models/GenericTable.php @@ -42,7 +42,7 @@ class GenericTable extends PageIndex // Should we create a page index? $this->items_per_page = !empty($options['items_per_page']) ? $options['items_per_page'] : 30; $this->needsPageIndex = !empty($this->items_per_page) && $this->recordCount > $this->items_per_page; - $this->index_class = isset($options['index_class']) ? $options['index_class'] : ''; + $this->index_class = $options['index_class'] ?? ''; // Figure out where to start. $this->start = empty($options['start']) || !is_numeric($options['start']) || $options['start'] < 0 || $options['start'] > $this->recordCount ? 0 : $options['start']; @@ -50,10 +50,6 @@ class GenericTable extends PageIndex // Let's bear a few things in mind... $this->base_url = $options['base_url']; - // This should be set at all times, too. - if (empty($options['no_items_label'])) - $options['no_items_label'] = ''; - // Gather parameters for the data gather function first. $parameters = [$this->start, $this->items_per_page, $options['sort_order'], $options['sort_direction']]; if (!empty($options['get_data_params']) && is_array($options['get_data_params'])) @@ -77,18 +73,18 @@ class GenericTable extends PageIndex // Not a single row in sight? if (empty($rows)) - $this->body = $options['no_items_label']; + $this->body = $options['no_items_label'] ?? ''; // Otherwise, parse it all! else $this->parseAllRows($rows, $options); // Got a title? - $this->title = isset($options['title']) ? htmlentities($options['title']) : ''; - $this->title_class = isset($options['title_class']) ? $options['title_class'] : ''; + $this->title = $options['title'] ?? ''; + $this->title_class = $options['title_class'] ?? ''; // Maybe even a form or two? - $this->form_above = isset($options['form_above']) ? $options['form_above'] : (isset($options['form']) ? $options['form'] : null); - $this->form_below = isset($options['form_below']) ? $options['form_below'] : (isset($options['form']) ? $options['form'] : null); + $this->form_above = $options['form_above'] ?? $options['form'] ?? null; + $this->form_below = $options['form_below'] ?? $options['form'] ?? null; } private function generateColumnHeaders($options) diff --git a/templates/FormView.php b/templates/FormView.php index 7ab40ff..47c52ec 100644 --- a/templates/FormView.php +++ b/templates/FormView.php @@ -25,7 +25,7 @@ class FormView extends SubTemplate if (!empty($this->title)) echo '
-

', $this->title, '

'; +

', htmlspecialchars($this->title), '

'; foreach ($this->_subtemplates as $template) $template->html_main(); From cba42a9129f89cffa985c90970257a87d1973b76 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 17 Feb 2021 16:41:58 +0100 Subject: [PATCH 3/9] Refactor GenericTable to use PageIndex rather than inherit from it This has on my todo list for years... I'm glad to finally get around to it. --- models/GenericTable.php | 51 +++++++++++++++++++++++++++------------ models/PageIndex.php | 30 ++++++++++++++++------- templates/TabularData.php | 13 +++++++--- 3 files changed, 66 insertions(+), 28 deletions(-) diff --git a/models/GenericTable.php b/models/GenericTable.php index 729d414..89f6c4c 100644 --- a/models/GenericTable.php +++ b/models/GenericTable.php @@ -6,11 +6,12 @@ * Kabuki CMS (C) 2013-2015, Aaron van Geffen *****************************************************************************/ -class GenericTable extends PageIndex +class GenericTable { protected $header = []; protected $body = []; - protected $page_index = []; + protected $pageIndex = null; + protected $currentPage = 1; protected $title; protected $title_class; @@ -36,17 +37,19 @@ class GenericTable extends PageIndex // Make sure we know whether we can actually sort on something. $this->tableIsSortable = !empty($options['base_url']); - // How much stuff do we have? + // How much data do we have? $this->recordCount = $options['get_count'](...(!empty($options['get_count_params']) ? $options['get_count_params'] : [])); - // Should we create a page index? + // How much data do we need to retrieve? $this->items_per_page = !empty($options['items_per_page']) ? $options['items_per_page'] : 30; - $this->needsPageIndex = !empty($this->items_per_page) && $this->recordCount > $this->items_per_page; - $this->index_class = $options['index_class'] ?? ''; // Figure out where to start. $this->start = empty($options['start']) || !is_numeric($options['start']) || $options['start'] < 0 || $options['start'] > $this->recordCount ? 0 : $options['start']; + // Figure out where we are on the whole, too. + $numPages = ceil($this->recordCount / $this->items_per_page); + $this->currentPage = min(ceil($this->start / $this->items_per_page) + 1, $numPages); + // Let's bear a few things in mind... $this->base_url = $options['base_url']; @@ -67,9 +70,10 @@ class GenericTable extends PageIndex // Okay, now for the column headers... $this->generateColumnHeaders($options); - // Generate a pagination if requested - if ($this->needsPageIndex) - $this->generatePageIndex(); + // Should we create a page index? + $needsPageIndex = !empty($this->items_per_page) && $this->recordCount > $this->items_per_page; + if ($needsPageIndex) + $this->generatePageIndex($options); // Not a single row in sight? if (empty($rows)) @@ -108,6 +112,19 @@ class GenericTable extends PageIndex } } + private function generatePageIndex($options) + { + $this->pageIndex = new PageIndex([ + 'base_url' => $this->base_url, + 'index_class' => $options['index_class'] ?? '', + 'items_per_page' => $this->items_per_page, + 'recordCount' => $this->recordCount, + 'sort_direction' => $this->sort_direction, + 'sort_order' => $this->sort_order, + 'start' => $this->start, + ]); + } + private function parseAllRows($rows, $options) { foreach ($rows as $i => $row) @@ -220,12 +237,6 @@ class GenericTable extends PageIndex return $this->start; } - public function getArray() - { - // Makes no sense to call it for a table, but inherits from PageIndex due to poor design, sorry. - throw new Exception('Function call is ambiguous.'); - } - public function getHeader() { return $this->header; @@ -236,6 +247,16 @@ class GenericTable extends PageIndex return $this->body; } + public function getCurrentPage() + { + return $this->currentPage; + } + + public function getPageIndex() + { + return $this->pageIndex; + } + public function getTitle() { return $this->title; diff --git a/models/PageIndex.php b/models/PageIndex.php index 0f17c0e..a0ebced 100644 --- a/models/PageIndex.php +++ b/models/PageIndex.php @@ -8,23 +8,35 @@ class PageIndex { - protected $page_index = []; + protected $base_url; protected $current_page = 1; + protected $index_class = 'pagination'; protected $items_per_page = 0; protected $needsPageIndex = false; protected $num_pages = 1; - protected $recordCount = 0; - protected $start = 0; - protected $sort_order = null; - protected $sort_direction = null; - protected $base_url; - protected $index_class = 'pagination'; + protected $page_index = []; protected $page_slug = '%AMP%page=%PAGE%'; + protected $recordCount = 0; + protected $sort_direction = null; + protected $sort_order = null; + protected $start = 0; public function __construct($options) { - foreach ($options as $key => $value) - $this->$key = $value; + static $neededKeys = ['base_url', 'items_per_page', 'recordCount']; + foreach ($neededKeys as $key) + { + if (!isset($options[$key])) + throw new Exception('PageIndex: argument ' . $key . ' missing in options'); + + $this->$key = $options[$key]; + } + + static $optionalKeys = ['index_class', 'page_slug', 'sort_direction', 'sort_order', 'start']; + foreach ($optionalKeys as $key) + if (isset($options[$key])) + $this->$key = $options[$key]; + $this->generatePageIndex(); } diff --git a/templates/TabularData.php b/templates/TabularData.php index 8460158..7f78659 100644 --- a/templates/TabularData.php +++ b/templates/TabularData.php @@ -6,12 +6,15 @@ * Kabuki CMS (C) 2013-2015, Aaron van Geffen *****************************************************************************/ -class TabularData extends Pagination +class TabularData extends SubTemplate { public function __construct(GenericTable $table) { $this->_t = $table; - parent::__construct($table); + + $pageIndex = $table->getPageIndex(); + if ($pageIndex) + $this->pager = new Pagination($pageIndex); } protected function html_content() @@ -25,7 +28,8 @@ class TabularData extends Pagination

', $title, '

'; // Showing a page index? - parent::html_content(); + if (isset($this->pager)) + $this->pager->html_content(); // Maybe even a small form? if (isset($this->_t->form_above)) @@ -87,7 +91,8 @@ class TabularData extends Pagination $this->showForm($this->_t->form_below); // Showing a page index? - parent::html_content(); + if (isset($this->pager)) + $this->pager->html_content(); echo '
'; From 681af0798500910930efb906ae949167fcda1e67 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 17 Feb 2021 20:06:33 +0100 Subject: [PATCH 4/9] Pass builder function for custom pagination link generation. This makes pagination for GenericTables work properly again. --- models/GenericTable.php | 1 + models/PageIndex.php | 26 +++++++++++++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/models/GenericTable.php b/models/GenericTable.php index 89f6c4c..d8ac071 100644 --- a/models/GenericTable.php +++ b/models/GenericTable.php @@ -118,6 +118,7 @@ class GenericTable 'base_url' => $this->base_url, 'index_class' => $options['index_class'] ?? '', 'items_per_page' => $this->items_per_page, + 'linkBuilder' => [$this, 'getLink'], 'recordCount' => $this->recordCount, 'sort_direction' => $this->sort_direction, 'sort_order' => $this->sort_order, diff --git a/models/PageIndex.php b/models/PageIndex.php index a0ebced..fe8a1a0 100644 --- a/models/PageIndex.php +++ b/models/PageIndex.php @@ -12,6 +12,7 @@ class PageIndex protected $current_page = 1; protected $index_class = 'pagination'; protected $items_per_page = 0; + private $linkBuilder; protected $needsPageIndex = false; protected $num_pages = 1; protected $page_index = []; @@ -32,7 +33,7 @@ class PageIndex $this->$key = $options[$key]; } - static $optionalKeys = ['index_class', 'page_slug', 'sort_direction', 'sort_order', 'start']; + static $optionalKeys = ['index_class', 'linkBuilder', 'page_slug', 'sort_direction', 'sort_order', 'start']; foreach ($optionalKeys as $key) if (isset($options[$key])) $this->$key = $options[$key]; @@ -40,6 +41,14 @@ class PageIndex $this->generatePageIndex(); } + private function buildLink($start = null, $order = null, $dir = null) + { + if (isset($this->linkBuilder)) + return call_user_func($this->linkBuilder, $start, $order, $dir); + else + return $this->getLink($start, $order, $dir); + } + protected function generatePageIndex() { /* @@ -80,7 +89,7 @@ class PageIndex $this->page_index[$p] = [ 'index' => $p, 'is_selected' => $this->current_page == $p, - 'href'=> $this->getLink(($p - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction), + 'href'=> $this->buildLink(($p - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction), ]; // The center of the page index. @@ -93,7 +102,7 @@ class PageIndex $this->page_index[$center] = [ 'index' => $center, 'is_selected' => $this->current_page == $center, - 'href'=> $this->getLink(($center - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction), + 'href'=> $this->buildLink(($center - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction), ]; } @@ -106,7 +115,7 @@ class PageIndex $this->page_index[$p] = [ 'index' => $p, 'is_selected' => $this->current_page == $p, - 'href'=> $this->getLink(($p - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction), + 'href'=> $this->buildLink(($p - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction), ]; // The center of the page index. @@ -119,7 +128,7 @@ class PageIndex $this->page_index[$center] = [ 'index' => $center, 'is_selected' => $this->current_page == $center, - 'href'=> $this->getLink(($center - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction), + 'href'=> $this->buildLink(($center - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction), ]; } @@ -132,7 +141,7 @@ class PageIndex $this->page_index[$p] = [ 'index' => $p, 'is_selected' => $this->current_page == $p, - 'href'=> $this->getLink(($p - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction), + 'href'=> $this->buildLink(($p - 1) * $this->items_per_page, $this->sort_order, $this->sort_direction), ]; // Previous page? @@ -169,11 +178,6 @@ class PageIndex return $url; } - public function getArray() - { - return $this->page_index; - } - public function getPageIndex() { return $this->page_index; From af73f007013eaa5469fc8cd0ef0b677e57a4042a Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 17 Feb 2021 20:08:22 +0100 Subject: [PATCH 5/9] Restrict access to GenericTable, Pagination class members. --- models/GenericTable.php | 18 +++++++----------- models/PageIndex.php | 24 ++++++++++++------------ 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/models/GenericTable.php b/models/GenericTable.php index d8ac071..eb540c1 100644 --- a/models/GenericTable.php +++ b/models/GenericTable.php @@ -8,18 +8,14 @@ class GenericTable { - protected $header = []; - protected $body = []; - protected $pageIndex = null; - protected $currentPage = 1; + private $header = []; + private $body = []; + private $pageIndex = null; + private $currentPage = 1; - protected $title; - protected $title_class; - protected $tableIsSortable = false; - protected $recordCount; - protected $needsPageIndex = false; - protected $current_page; - protected $num_pages; + private $title; + private $title_class; + private $tableIsSortable = false; public $form_above; public $form_below; diff --git a/models/PageIndex.php b/models/PageIndex.php index fe8a1a0..6033c9a 100644 --- a/models/PageIndex.php +++ b/models/PageIndex.php @@ -8,19 +8,19 @@ class PageIndex { - protected $base_url; - protected $current_page = 1; - protected $index_class = 'pagination'; - protected $items_per_page = 0; + private $base_url; + private $current_page = 1; + private $index_class = 'pagination'; + private $items_per_page = 0; private $linkBuilder; - protected $needsPageIndex = false; - protected $num_pages = 1; - protected $page_index = []; - protected $page_slug = '%AMP%page=%PAGE%'; - protected $recordCount = 0; - protected $sort_direction = null; - protected $sort_order = null; - protected $start = 0; + private $needsPageIndex = false; + private $num_pages = 1; + private $page_index = []; + private $page_slug = '%AMP%page=%PAGE%'; + private $recordCount = 0; + private $sort_direction = null; + private $sort_order = null; + private $start = 0; public function __construct($options) { From 6c662481bc6d304307c484e47bc5ec233990e5b1 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 17 Feb 2021 20:15:31 +0100 Subject: [PATCH 6/9] Remove a few obscure, unused features. * Removed support for row classification. Use of CSS is preferred. * Removed support for disabling/enabling columns via a property. Unset as needed. * Removed support for passing and inheriting a cell width by column. Header width suffices. --- models/GenericTable.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/models/GenericTable.php b/models/GenericTable.php index eb540c1..72d1d33 100644 --- a/models/GenericTable.php +++ b/models/GenericTable.php @@ -126,20 +126,12 @@ class GenericTable { foreach ($rows as $i => $row) { - $className = $i & 1 ? 'even' : 'odd'; - if (isset($options['row_classifier'])) - $className .= $options['row_classifier']($row); - $newRow = [ - 'class' => $className, 'cells' => [], ]; foreach ($options['columns'] as $column) { - if (isset($column['enabled']) && $column['enabled'] == false) - continue; - // The hard way? if (isset($column['parse'])) { @@ -207,7 +199,6 @@ class GenericTable // Append the cell to the row. $newRow['cells'][] = [ - 'width' => !empty($column['cell_width']) && is_int($column['cell_width']) ? $column['cell_width'] : null, 'value' => $value, ]; } From ff808ba18dd10c28c0fad24893cda4276678fce6 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 17 Feb 2021 20:35:30 +0100 Subject: [PATCH 7/9] Refactor processing of raw rows and their cell data. --- models/GenericTable.php | 189 ++++++++++++++++++++-------------------- 1 file changed, 96 insertions(+), 93 deletions(-) diff --git a/models/GenericTable.php b/models/GenericTable.php index 72d1d33..c7d2ef2 100644 --- a/models/GenericTable.php +++ b/models/GenericTable.php @@ -57,8 +57,8 @@ class GenericTable // Okay, let's fetch the data! $data = $options['get_data'](...$parameters); - // Clean up a bit. - $rows = $data['rows']; + // Extract data into local variables. + $rawRowData = $data['rows']; $this->sort_order = $data['order']; $this->sort_direction = $data['direction']; unset($data); @@ -71,12 +71,11 @@ class GenericTable if ($needsPageIndex) $this->generatePageIndex($options); - // Not a single row in sight? - if (empty($rows)) - $this->body = $options['no_items_label'] ?? ''; - // Otherwise, parse it all! + // Process the data to be shown into rows. + if (!empty($rawRowData)) + $this->processAllRows($rawRowData, $options); else - $this->parseAllRows($rows, $options); + $this->body = $options['no_items_label'] ?? ''; // Got a title? $this->title = $options['title'] ?? ''; @@ -122,92 +121,6 @@ class GenericTable ]); } - private function parseAllRows($rows, $options) - { - foreach ($rows as $i => $row) - { - $newRow = [ - 'cells' => [], - ]; - - foreach ($options['columns'] as $column) - { - // The hard way? - if (isset($column['parse'])) - { - if (!isset($column['parse']['type'])) - $column['parse']['type'] = 'value'; - - // Parse the basic value first. - switch ($column['parse']['type']) - { - // value: easy as pie. - default: - case 'value': - $value = $row[$column['parse']['data']]; - break; - - // sprintf: filling the gaps! - case 'sprintf': - $parameters = [$column['parse']['data']['pattern']]; - foreach ($column['parse']['data']['arguments'] as $identifier) - $parameters[] = $row[$identifier]; - $value = sprintf(...$parameters); - break; - - // timestamps: let's make them readable! - case 'timestamp': - if (empty($column['parse']['data']['pattern']) || $column['parse']['data']['pattern'] === 'long') - $pattern = '%F %H:%M'; - elseif ($column['parse']['data']['pattern'] === 'short') - $pattern = '%F'; - else - $pattern = $column['parse']['data']['pattern']; - - if (!is_numeric($row[$column['parse']['data']['timestamp']])) - $timestamp = strtotime($row[$column['parse']['data']['timestamp']]); - else - $timestamp = (int) $row[$column['parse']['data']['timestamp']]; - - if (isset($column['parse']['data']['if_null']) && $timestamp == 0) - $value = $column['parse']['data']['if_null']; - else - $value = strftime($pattern, $timestamp); - break; - - // function: the flexible way! - case 'function': - $value = $column['parse']['data']($row); - break; - } - - // Generate a link, if requested. - if (!empty($column['parse']['link'])) - { - // First, generate the replacement variables. - $keys = array_keys($row); - $values = array_values($row); - foreach ($keys as $keyKey => $keyValue) - $keys[$keyKey] = '{' . strtoupper($keyValue) . '}'; - - $value = '' . $value . ''; - } - } - // The easy way! - else - $value = $row[$column['value']]; - - // Append the cell to the row. - $newRow['cells'][] = [ - 'value' => $value, - ]; - } - - // Append the new row in the body. - $this->body[] = $newRow; - } - } - public function getLink($start = null, $order = null, $dir = null) { if ($start === null) @@ -254,4 +167,94 @@ class GenericTable { return $this->title_class; } + + private function processAllRows($rows, $options) + { + foreach ($rows as $i => $row) + { + $newRow = [ + 'cells' => [], + ]; + + foreach ($options['columns'] as $column) + { + // Process data for this particular cell. + if (isset($column['parse'])) + $value = self::processCell($column['parse'], $row); + else + $value = $row[$column['value']]; + + // Append the cell to the row. + $newRow['cells'][] = [ + 'value' => $value, + ]; + } + + // Append the new row in the body. + $this->body[] = $newRow; + } + } + + private function processCell($options, $rowData) + { + if (!isset($options['type'])) + $options['type'] = 'value'; + + // Parse the basic value first. + switch ($options['type']) + { + // Basic option: simply take a use a particular data property. + case 'value': + $value = $rowData[$options['data']]; + break; + + // Processing via a lambda function. + case 'function': + $value = $options['data']($rowData); + break; + + // Using sprintf to fill out a particular pattern. + case 'sprintf': + $parameters = [$options['data']['pattern']]; + foreach ($options['data']['arguments'] as $identifier) + $parameters[] = $rowData[$identifier]; + + $value = sprintf(...$parameters); + break; + + // Timestamps get custom treatment. + case 'timestamp': + if (empty($options['data']['pattern']) || $options['data']['pattern'] === 'long') + $pattern = '%F %H:%M'; + elseif ($options['data']['pattern'] === 'short') + $pattern = '%F'; + else + $pattern = $options['data']['pattern']; + + if (!is_numeric($rowData[$options['data']['timestamp']])) + $timestamp = strtotime($rowData[$options['data']['timestamp']]); + else + $timestamp = (int) $rowData[$options['data']['timestamp']]; + + if (isset($options['data']['if_null']) && $timestamp == 0) + $value = $options['data']['if_null']; + else + $value = strftime($pattern, $timestamp); + break; + } + + // Generate a link, if requested. + if (!empty($options['link'])) + { + // First, generate the replacement variables. + $keys = array_keys($rowData); + $values = array_values($rowData); + foreach ($keys as $keyKey => $keyValue) + $keys[$keyKey] = '{' . strtoupper($keyValue) . '}'; + + $value = '' . $value . ''; + } + + return $value; + } } From 4bf464142843c43f59e55b748bb35ecdb280894f Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 17 Feb 2021 20:38:27 +0100 Subject: [PATCH 8/9] Minor refactor of generateColumnHeaders function --- models/GenericTable.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/models/GenericTable.php b/models/GenericTable.php index c7d2ef2..b076df1 100644 --- a/models/GenericTable.php +++ b/models/GenericTable.php @@ -93,10 +93,13 @@ class GenericTable if (empty($column['header'])) continue; + $isSortable = $this->tableIsSortable && !empty($column['is_sortable']); + $sortDirection = $key == $this->sort_order && $this->sort_direction === 'up' ? 'down' : 'up'; + $header = [ 'class' => isset($column['class']) ? $column['class'] : '', 'colspan' => !empty($column['header_colspan']) ? $column['header_colspan'] : 1, - 'href' => !$this->tableIsSortable || empty($column['is_sortable']) ? '' : $this->getLink($this->start, $key, $key == $this->sort_order && $this->sort_direction == 'up' ? 'down' : 'up'), + 'href' => $isSortable ? $this->getLink($this->start, $key, $sortDirection) : null, 'label' => $column['header'], 'scope' => 'col', 'sort_mode' => $key == $this->sort_order ? $this->sort_direction : null, From 237f4005bdfc5632884773516298ad0b9aa1ff46 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Wed, 17 Feb 2021 22:44:26 +0100 Subject: [PATCH 9/9] Apply htmlspecialchars to basic values. --- models/GenericTable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/GenericTable.php b/models/GenericTable.php index b076df1..9356cce 100644 --- a/models/GenericTable.php +++ b/models/GenericTable.php @@ -208,7 +208,7 @@ class GenericTable { // Basic option: simply take a use a particular data property. case 'value': - $value = $rowData[$options['data']]; + $value = htmlspecialchars($rowData[$options['data']]); break; // Processing via a lambda function.