GenericTable: refactor order and pagination initalisation

This commit is contained in:
Aaron van Geffen 2024-12-19 15:00:00 +01:00
parent 06c95853f5
commit bb8a8bad27
6 changed files with 85 additions and 118 deletions

View File

@ -54,27 +54,19 @@ class ManageAlbums extends HTMLController
'value' => 'count',
],
],
'start' => !empty($_GET['start']) ? (int) $_GET['start'] : 0,
'sort_order' => !empty($_GET['order']) ? $_GET['order'] : null,
'sort_direction' => !empty($_GET['dir']) ? $_GET['dir'] : null,
'default_sort_order' => 'tag',
'default_sort_direction' => 'up',
'start' => $_GET['start'] ?? 0,
'sort_order' => $_GET['order'] ?? '',
'sort_direction' => $_GET['dir'] ?? '',
'title' => 'Manage albums',
'no_items_label' => 'No albums meet the requirements of the current filter.',
'items_per_page' => 9999,
'index_class' => 'col-md-6',
'base_url' => BASEURL . '/managealbums/',
'get_data' => function($offset = 0, $limit = 9999, $order = '', $direction = 'up') {
if (!in_array($order, ['id_tag', 'tag', 'slug', 'count']))
$order = 'tag';
if (!in_array($direction, ['up', 'down']))
$direction = 'up';
$rows = PhotoAlbum::getHierarchy($order, $direction);
return [
'rows' => $rows,
'order' => $order,
'direction' => ($direction == 'up' ? 'up' : 'down'),
];
'get_data' => function($offset, $limit, $order, $direction) {
assert(in_array($order, ['id_tag', 'tag', 'slug', 'count']));
return PhotoAlbum::getHierarchy($order, $direction);
},
'get_count' => function() {
return 9999;

View File

@ -121,19 +121,20 @@ class ManageAssets extends HTMLController
],
],
],
'start' => !empty($_GET['start']) ? (int) $_GET['start'] : 0,
'sort_order' => !empty($_GET['order']) ? $_GET['order'] : '',
'sort_direction' => !empty($_GET['dir']) ? $_GET['dir'] : '',
'default_sort_order' => 'id_asset',
'default_sort_direction' => 'down',
'start' => $_GET['start'] ?? 0,
'sort_order' => $_GET['order'] ?? '',
'sort_direction' => $_GET['dir'] ?? '',
'title' => 'Manage assets',
'no_items_label' => 'No assets meet the requirements of the current filter.',
'items_per_page' => 30,
'index_class' => 'col-md-6',
'base_url' => BASEURL . '/manageassets/',
'get_data' => function($offset = 0, $limit = 30, $order = '', $direction = 'down') {
if (!in_array($order, ['id_asset', 'id_user_uploaded', 'title', 'subdir', 'filename']))
$order = 'id_asset';
'get_data' => function($offset, $limit, $order, $direction) {
assert(in_array($order, ['id_asset', 'id_user_uploaded', 'title', 'subdir', 'filename']));
$data = Registry::get('db')->queryAssocs('
return Registry::get('db')->queryAssocs('
SELECT a.id_asset, a.subdir, a.filename,
a.image_width, a.image_height, a.mimetype,
u.id_user, u.first_name, u.surname
@ -146,12 +147,6 @@ class ManageAssets extends HTMLController
'offset' => $offset,
'limit' => $limit,
]);
return [
'rows' => $data,
'order' => $order,
'direction' => $direction,
];
},
'get_count' => 'Asset::getCount',
];

View File

@ -14,8 +14,8 @@ class ManageErrors extends HTMLController
if (!Registry::get('user')->isAdmin())
throw new NotAllowedException();
// Flushing, are we?
if (isset($_POST['flush']) && Session::validateSession('get'))
// Clearing, are we?
if (isset($_POST['clear']) && Session::validateSession('get'))
{
ErrorLog::flush();
header('Location: ' . BASEURL . '/manageerrors/');
@ -31,7 +31,7 @@ class ManageErrors extends HTMLController
'method' => 'post',
'class' => 'col-md-6 text-end',
'buttons' => [
'flush' => [
'clear' => [
'type' => 'submit',
'caption' => 'Delete all',
'class' => 'btn-danger',
@ -39,7 +39,7 @@ class ManageErrors extends HTMLController
],
],
'columns' => [
'id' => [
'id_entry' => [
'value' => 'id_entry',
'header' => '#',
'is_sortable' => true,
@ -95,19 +95,20 @@ class ManageErrors extends HTMLController
],
],
],
'start' => !empty($_GET['start']) ? (int) $_GET['start'] : 0,
'sort_order' => !empty($_GET['order']) ? $_GET['order'] : '',
'sort_direction' => !empty($_GET['dir']) ? $_GET['dir'] : '',
'default_sort_order' => 'id_entry',
'default_sort_direction' => 'down',
'start' => $_GET['start'] ?? 0,
'sort_order' => $_GET['order'] ?? '',
'sort_direction' => $_GET['dir'] ?? '',
'no_items_label' => "No errors to display -- we're all good!",
'items_per_page' => 20,
'index_class' => 'col-md-6',
'base_url' => BASEURL . '/manageerrors/',
'get_count' => 'ErrorLog::getCount',
'get_data' => function($offset = 0, $limit = 20, $order = '', $direction = 'down') {
if (!in_array($order, ['id_entry', 'file', 'line', 'time', 'ipaddress', 'id_user']))
$order = 'id_entry';
'get_data' => function($offset, $limit, $order, $direction) {
assert(in_array($order, ['id_entry', 'file', 'line', 'time', 'ipaddress', 'id_user']));
$data = Registry::get('db')->queryAssocs('
return Registry::get('db')->queryAssocs('
SELECT *
FROM log_errors
ORDER BY {raw:order}
@ -117,12 +118,6 @@ class ManageErrors extends HTMLController
'offset' => $offset,
'limit' => $limit,
]);
return [
'rows' => $data,
'order' => $order,
'direction' => $direction,
];
},
];

View File

@ -70,21 +70,20 @@ class ManageTags extends HTMLController
'value' => 'count',
],
],
'start' => !empty($_GET['start']) ? (int) $_GET['start'] : 0,
'sort_order' => !empty($_GET['order']) ? $_GET['order'] : null,
'sort_direction' => !empty($_GET['dir']) ? $_GET['dir'] : null,
'default_sort_order' => 'tag',
'default_sort_direction' => 'up',
'start' => $_GET['start'] ?? 0,
'sort_order' => $_GET['order'] ?? '',
'sort_direction' => $_GET['dir'] ?? '',
'title' => 'Manage tags',
'no_items_label' => 'No tags meet the requirements of the current filter.',
'items_per_page' => 30,
'index_class' => 'col-md-6',
'base_url' => BASEURL . '/managetags/',
'get_data' => function($offset = 0, $limit = 30, $order = '', $direction = 'up') {
if (!in_array($order, ['id_tag', 'tag', 'slug', 'kind', 'count']))
$order = 'tag';
if (!in_array($direction, ['up', 'down']))
$direction = 'up';
'get_data' => function($offset, $limit, $order, $direction) {
assert(in_array($order, ['id_tag', 'tag', 'slug', 'count']));
$data = Registry::get('db')->queryAssocs('
return Registry::get('db')->queryAssocs('
SELECT t.*, u.id_user, u.first_name, u.surname
FROM tags AS t
LEFT JOIN users AS u ON t.id_user_owner = u.id_user
@ -97,12 +96,6 @@ class ManageTags extends HTMLController
'limit' => $limit,
'album' => 'Album',
]);
return [
'rows' => $data,
'order' => $order,
'direction' => ($direction == 'up' ? 'up' : 'down'),
];
},
'get_count' => function() {
return Registry::get('db')->queryValue('

View File

@ -90,19 +90,20 @@ class ManageUsers extends HTMLController
],
],
],
'start' => !empty($_GET['start']) ? (int) $_GET['start'] : 0,
'sort_order' => !empty($_GET['order']) ? $_GET['order'] : '',
'sort_direction' => !empty($_GET['dir']) ? $_GET['dir'] : '',
'default_sort_order' => 'id_user',
'default_sort_direction' => 'down',
'start' => $_GET['start'] ?? 0,
'sort_order' => $_GET['order'] ?? '',
'sort_direction' => $_GET['dir'] ?? '',
'title' => 'Manage users',
'no_items_label' => 'No users meet the requirements of the current filter.',
'items_per_page' => 30,
'index_class' => 'col-md-6',
'base_url' => BASEURL . '/manageusers/',
'get_data' => function($offset = 0, $limit = 30, $order = '', $direction = 'down') {
if (!in_array($order, ['id_user', 'surname', 'first_name', 'slug', 'emailaddress', 'last_action_time', 'ip_address', 'is_admin']))
$order = 'id_user';
'get_data' => function($offset, $limit, $order, $direction) {
assert(in_array($order, ['id_user', 'surname', 'first_name', 'slug', 'emailaddress', 'last_action_time', 'ip_address', 'is_admin']));
$data = Registry::get('db')->queryAssocs('
return Registry::get('db')->queryAssocs('
SELECT *
FROM users
ORDER BY {raw:order}
@ -112,18 +113,8 @@ class ManageUsers extends HTMLController
'offset' => $offset,
'limit' => $limit,
]);
return [
'rows' => $data,
'order' => $order,
'direction' => $direction,
];
},
'get_count' => function() {
return Registry::get('db')->queryValue('
SELECT COUNT(*)
FROM users');
}
'get_count' => 'Member::getCount',
];
$table = new GenericTable($options);

View File

@ -28,53 +28,22 @@ class GenericTable
public function __construct($options)
{
// Make sure we're actually sorting on something sortable.
if (!isset($options['sort_order']) || (!empty($options['sort_order']) && empty($options['columns'][$options['sort_order']]['is_sortable'])))
$options['sort_order'] = '';
$this->initOrder($options);
$this->initPagination($options);
// Order in which direction?
if (!empty($options['sort_direction']) && !in_array($options['sort_direction'], ['up', 'down']))
$options['sort_direction'] = 'up';
// How much data do we have?
$this->recordCount = $options['get_count']();
// How much data do we need to retrieve?
$this->items_per_page = !empty($options['items_per_page']) ? $options['items_per_page'] : 30;
// 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 = max(1, 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'];
// Gather parameters for the data gather function first.
$parameters = [$this->start, $this->items_per_page, $options['sort_order'], $options['sort_direction']];
// Okay, let's fetch the data!
$data = $options['get_data'](...$parameters);
// Extract data into local variables.
$rawRowData = $data['rows'];
$this->sort_order = $data['order'];
$this->sort_direction = $data['direction'];
unset($data);
$data = $options['get_data']($this->start, $this->items_per_page,
$this->sort_order, $this->sort_direction);
// Okay, now for the column headers...
$this->generateColumnHeaders($options);
// Should we create a page index?
$needsPageIndex = !empty($this->items_per_page) && $this->recordCount > $this->items_per_page;
if ($needsPageIndex)
if ($this->recordCount > $this->items_per_page)
$this->generatePageIndex($options);
// Process the data to be shown into rows.
if (!empty($rawRowData))
$this->processAllRows($rawRowData, $options);
if (!empty($data))
$this->processAllRows($data, $options);
else
$this->body = $options['no_items_label'] ?? '';
@ -89,6 +58,38 @@ class GenericTable
$this->form_below = $options['form_below'] ?? $options['form'] ?? null;
}
private function initOrder($options)
{
assert(isset($options['default_sort_order']));
assert(isset($options['default_sort_direction']));
// Validate sort order (column)
$this->sort_order = $options['sort_order'];
if (empty($this->sort_order) || empty($options['columns'][$this->sort_order]['is_sortable']))
$this->sort_order = $options['default_sort_order'];
// Validate sort direction
$this->sort_direction = $options['sort_direction'];
if (empty($this->sort_direction) || !in_array($this->sort_direction, ['up', 'down']))
$this->sort_direction = $options['default_sort_direction'];
}
private function initPagination(array $options)
{
assert(isset($options['base_url']));
assert(isset($options['items_per_page']));
$this->base_url = $options['base_url'];
$this->recordCount = $options['get_count']();
$this->items_per_page = !empty($options['items_per_page']) ? $options['items_per_page'] : 30;
$this->start = empty($options['start']) || !is_numeric($options['start']) || $options['start'] < 0 || $options['start'] > $this->recordCount ? 0 : $options['start'];
$numPages = max(1, ceil($this->recordCount / $this->items_per_page));
$this->currentPage = min(ceil($this->start / $this->items_per_page) + 1, $numPages);
}
private function generateColumnHeaders($options)
{
foreach ($options['columns'] as $key => $column)
@ -218,7 +219,7 @@ class GenericTable
{
// Basic option: simply take a use a particular data property.
case 'value':
$value = htmlspecialchars($rowData[$options['data']]);
$value = htmlspecialchars($rowData[$options['data']] ?? '');
break;
// Processing via a lambda function.