<?php
/**
* SeekQuarry/Yioop --
* Open Source Pure PHP Search Engine, Crawler, and Indexer
*
* Copyright (C) 2009 - 2026 Chris Pollett chris@pollett.org
*
* LICENSE:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* END LICENSE
*
* @author Chris Pollett chris@pollett.org
* @license https://www.gnu.org/licenses/ GPL3
* @link https://www.seekquarry.com/
* @copyright 2009 - 2026
* @filesource
*/
namespace seekquarry\yioop\views\helpers;
use seekquarry\yioop as B;
use seekquarry\yioop\configs as C;
/**
* Used to create links to go backward/forwards and search a database
* tables. HTML table with data representing a
* database table might have millions of rows so want to
* limit what the user actually gets at one time and just
* allow the user to "page" through in increments of
* 10, 20, 50, 100, 200 rows at a time.
*
* @author Chris Pollett
*/
class PagingtableHelper extends Helper
{
/**
* The choices for how many rows out of the database table to display
* @var array
*/
public $show_choices = [
10 => 10, 20 => 20, 50 => 50, 100 => 100, 200 => 200
];
/**
* Used to render the links to go
* backwards and forwards through a database table. We have two separate
* functions for the mobile and desktop drawers.
*
* @param array $data fields of this contain values from the controller
* for the CSRF_TOKEN; NUM_TOTAL of rows; NUM_SHOW, the number to show;
* etc.
*/
public function render($data)
{
if (!isset($data['PAGING'])) {
$data['PAGING'] = "";
}
if ($_SERVER["MOBILE"]) {
$this->mobileTableControls($data);
} else {
$this->desktopTableControls($data);
}
}
/**
* Draws the heading before a paging table as well as the controls
* for what rows to see (mobile phone case).
*
* @param array $data needed for dropdown values for number of groups to
* display
*/
public function mobileTableControls($data)
{
$activity = $data['ACTIVITY'];
$admin_url = htmlentities(B\controllerUrl('admin', true));
$base_url = $admin_url . C\p('CSRF_TOKEN') . "=" .
$data[C\p('CSRF_TOKEN')].
"&a=$activity";
$data_fields = ['NUM_TOTAL', 'NUM_SHOW', 'START_ROW', 'END_ROW',
'NEXT_START', 'NEXT_END', 'PREV_START', 'PREV_END', 'FORM_TYPE'];
$var_prefix = (isset($data['VAR_PREFIX'])) ?
strtoupper($data['VAR_PREFIX']) : "";
$search_arg = (empty($data['SEARCH_ARG'])) ? 'search' :
$data['SEARCH_ARG'];
$icon_helper = $data['VIEW']->helper("iconlink");
foreach ($data_fields as $field) {
$d[$field] = $var_prefix . $field;
}
$start_row = $var_prefix . "start_row";
$end_row = $var_prefix . "end_row";
$num_show = $var_prefix . "num_show";
$this->drawTableTitle($data);
?>
<div>
<?php
$form_tag = !isset($data["NO_FORM_TAG"]) || !$data["NO_FORM_TAG"];
if ($form_tag) {
e('<form method="get">');
}
$name = isset($data['NAME']) ? $data['NAME'] : "";
$add_arg = (empty($data[$d['FORM_TYPE']]) &&
$d['FORM_TYPE'] == "FORM_TYPE") ? "" :
"&arg=" . $data[$d['FORM_TYPE']];
$add_arg = (!empty($data[$d['FORM_TYPE']])
&& $data[$d['FORM_TYPE']] == 'search') ?
"&arg=" . $data['SEARCH_ARG'] : $add_arg;
$bound_url = $base_url . $add_arg;
if (isset($data['browse'])) {
$bound_url .= "&browse=" . $data['browse'];
}
if ($name != "") {
$bound_url .= "&name=" . $name;
} ?>
<input type="hidden" name="c" value="admin" >
<input type="hidden" name="changeshow" value="true" >
<input type="hidden" name="<?= C\p('CSRF_TOKEN') ?>"
value="<?php e($data[C\p('CSRF_TOKEN')]); ?>" >
<input type="hidden" name="a" value="<?= $activity ?>" >
<?php
if (!empty($data['context']) || $data[$d['FORM_TYPE']] == 'search'){
?>
<input type="hidden" name="arg" value="<?=$search_arg ?>" >
<?php
}
if (!empty($data['browse'])) {
?>
<input type="hidden" name="browse" value="true" >
<?php
}
e("<b><label for='{$var_prefix}num-show'>".
tl('pagingtable_helper_show') . "</label></b>");
$data['VIEW']->helper("options")->render(
"{$var_prefix}num-show", "{$var_prefix}num_show",
$this->show_choices, $data[$d['NUM_SHOW']], true);
e("<br>");
if ($data[$d['START_ROW']] > 0) {
?>
<a href="<?= $bound_url . "&$start_row=".
$data[$d['PREV_START']] . "&$end_row=".
$data[$d['PREV_END']] . "&$num_show=".
$data[$d['NUM_SHOW']] . $data['PAGING'] ?>"><<</a>
<?php
}
e("<b>".tl('pagingtable_helper_row_range', $data[$d['START_ROW']],
$data[$d['END_ROW']], $data[$d['NUM_TOTAL']])."</b>");
if ($data[$d['END_ROW']] < $data[$d['NUM_TOTAL']]) {
?>
<a href="<?= $bound_url."&$start_row=".
$data[$d['NEXT_START']]."&$end_row=".
$data[$d['NEXT_END']]."&$num_show=".
$data[$d['NUM_SHOW']].$data['PAGING'] ?>" >>></a>
<?php
}
if (!isset($data['NO_SEARCH'])) {
if ($data[$d['FORM_TYPE']] != "search") {
$search_arg_field = (empty($search_arg)) ? "" :
'&arg='. $search_arg;
$icon_helper->renderLink(
$base_url . $search_arg_field, "search");
} else {
$icon_helper->renderLink($base_url , "search");
}
}
if ($form_tag) {
e('</form>');
}
?>
</div>
<?php
}
/**
* Draws the heading before the user table as well as the controls
* for what user to see (desktop, laptop, tablet case).
*
* @param array $data needed for dropdown values for number of groups to
* display
*/
public function desktopTableControls($data)
{
$activity = $data['ACTIVITY'];
$admin_url = htmlentities(B\controllerUrl('admin', true));
$base_url = $admin_url . C\p('CSRF_TOKEN')."=".$data[C\p('CSRF_TOKEN')].
"&a=$activity";
$data_fields = ['NUM_TOTAL', 'NUM_SHOW', 'START_ROW', 'END_ROW',
'NEXT_START', 'NEXT_END', 'PREV_START', 'PREV_END', 'FORM_TYPE'];
$var_prefix = (isset($data['VAR_PREFIX'])) ?
strtoupper($data['VAR_PREFIX']) : "";
$icon_helper = $data['VIEW']->helper("iconlink");
foreach ($data_fields as $field) {
$d[$field] = $var_prefix . $field;
}
$search_arg = (empty($data['SEARCH_ARG'])) ? 'search' :
$data['SEARCH_ARG'];
$start_row = $var_prefix . "start_row";
$end_row = $var_prefix . "end_row";
$num_show = $var_prefix . "num_show";
$class = 'class="table-margin float-opposite"';
$target_fragment = (isset($data["TARGET_FRAGMENT"])) ?
$data["TARGET_FRAGMENT"] : "";
$top = false;
if (isset( $data['NO_FLOAT_TABLE'] ) && $data['NO_FLOAT_TABLE'] ){
$class = "";
$top = true;
}
if ($top) {
$this->drawTableTitle($data);
}
?>
<div <?php e($class); ?>>
<?php
$form_tag = !isset($data["NO_FORM_TAG"]) || !$data["NO_FORM_TAG"];
if ($form_tag) {
e('<form method="get">');
}
$name = isset($data['NAME']) ? $data['NAME'] : "";
$add_arg = (empty($data[$d['FORM_TYPE']]) &&
$d['FORM_TYPE'] == "FORM_TYPE") ? "" :
"&arg=" . $data[$d['FORM_TYPE']];
$add_arg = (!empty($data['SEARCH_ARG'])
&& $data[$d['FORM_TYPE']] == 'search') ?
"&arg=" . $data['SEARCH_ARG'] : $add_arg;
$bound_url = $base_url . $add_arg;
if ($name != "") {
$bound_url .= "&name=" . $name;
}
if (isset($data['browse'])) {
$bound_url .= "&browse=" . $data['browse'];
}
if ($data[$d['START_ROW']] > 0) {
?>
<a href="<?= $bound_url . "&$start_row=".
$data[$d['PREV_START']] . "&$end_row=".
$data[$d['PREV_END']] . "&$num_show=".
$data[$d['NUM_SHOW']] . $data['PAGING'].
'#' . $target_fragment ?>"><<</a>
<?php
}
e("<b>".tl('pagingtable_helper_row_range', $data[$d['START_ROW']],
$data[$d['END_ROW']], $data[$d['NUM_TOTAL']])."</b>");
if ($data[$d['END_ROW']] < $data[$d['NUM_TOTAL']]) {
?>
<a href="<?= $bound_url . "&$start_row=" .
$data[$d['NEXT_START']] . "&$end_row=" .
$data[$d['NEXT_END']] . "&$num_show=" .
$data[$d['NUM_SHOW']].$data['PAGING'].
'#'.$target_fragment ?>" >>></a>
<?php
}
?>
<input type="hidden" name="c" value="admin" >
<input type="hidden" name="changeshow" value="true" >
<input type="hidden" name="<?= C\p('CSRF_TOKEN') ?>"
value="<?= $data[C\p('CSRF_TOKEN')] ?>" >
<input type="hidden" name="a" value="<?= $activity ?>" >
<?php
if (!empty($data['context']) || $data['FORM_TYPE'] == 'search'){
?>
<input type="hidden" name="arg" value="<?=$search_arg ?>" >
<?php
}
if (!empty($data['browse'])) {
?>
<input type="hidden" name="browse" value="true" >
<?php
}
e("<b><label for='{$var_prefix}num-show'>".
tl('pagingtable_helper_show') . "</label></b>");
$data['VIEW']->helper("options")->render(
"{$var_prefix}num-show", "{$var_prefix}num_show",
$this->show_choices,
$data[$d['NUM_SHOW']], true);
if (empty($data['NO_SEARCH'])) {
$add_browse = (empty($data['browse'])) ? "":
"&browse=" . $data['browse'];
$add_arg = (empty($data['DEFAULT_ARG'])) ? "":
"&arg=" . $data['DEFAULT_ARG'];
$add_search_arg = (empty($search_arg)) ? "":
"&arg=" . $search_arg;
if($data[$d['FORM_TYPE']] != "search") {
$search_url = $base_url . $add_search_arg .
$add_browse;
$icon_helper->renderLink($search_url, "search");
} else {
$icon_helper->renderLink($base_url . $add_arg .
$add_browse, "search");
}
}
if ($form_tag) {
e('</form>');
}?>
</div><?php
if (!$top) {
$this->drawTableTitle($data);
}
}
/**
* Draw title of heading on table as well as the add row form toggle
*
* @param array $data from controller/component to figure out localized
* table name ($data['TABLE_TITLE']) as well as the toggle state
* of the add row form $data['DISABLE_ADD_TOGGLE']
*/
public function drawTableTitle($data)
{
if (empty($data['TABLE_TITLE']) && !empty($data['NO_ADD_TOGGLE'])) {
return;
} ?>
<h2><?php
$toggle_id = (empty($data['TOGGLE_ID'])) ? 'admin-form-row' :
$data['TOGGLE_ID'];
$icon_helper = $data['VIEW']->helper("iconlink");
if (is_array($data['TABLE_TITLE']) && !empty($data['TABLE_TITLE'])) {
if (empty($data['TABLE_TITLE_SELECTED'])) {
$data['TABLE_TITLE_SELECTED'] = key('TABLE_TITLE');
}
$data['VIEW']->helper("options")->renderLinkDropDown('browse-state',
$data['TABLE_TITLE'], $data['TABLE_TITLE_SELECTED'], "");
} else {
e($data['TABLE_TITLE']);
}
$add_toggle = "";
$add_css = "small-margin no-padding";
if (empty($_REQUEST['noscript']) && empty($data['NO_ADD_TOGGLE'])) {
if (!empty($data['ALTERNATIVE_ADD_TOGGLE_URL'] )) {
$add_toggle = $icon_helper->renderButton(
$data['ALTERNATIVE_ADD_TOGGLE_URL'], "add", "", true,
$add_css);
} else if (empty($data['DISABLE_ADD_TOGGLE'])) {
$add_toggle = $icon_helper->renderButton(
"javascript:toggleDisplay(\"$toggle_id\")", "add", "", true,
$add_css);
} else {
$add_toggle = $icon_helper->renderButton(
"javascript:return false;", "add", "", true, $add_css .
" back-light-gray", "disabled");
}
}
if (empty($data['VIEW']->layout)) {
e($add_toggle);
} else {?>
<script>
document.write(<?=json_encode($add_toggle)?>);
</script>
<?php
}
if (!empty($data['TABLE_TITLE_HELP'])) {
e(" ".$data['TABLE_TITLE_HELP']);
}
?>
</h2><?php
}
}