From dfce1fea3c9f83584b08a2a7fed76f8e0761d818 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 17 Nov 2019 15:20:46 +0100 Subject: [PATCH] re-add \Froxlor\UI\Paging as it's still required for api_keys.php because they are not (yet) listable via API Signed-off-by: Michael Kaufmann --- lib/Froxlor/UI/Paging.php | 520 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 520 insertions(+) create mode 100644 lib/Froxlor/UI/Paging.php diff --git a/lib/Froxlor/UI/Paging.php b/lib/Froxlor/UI/Paging.php new file mode 100644 index 00000000..6b7e5ee7 --- /dev/null +++ b/lib/Froxlor/UI/Paging.php @@ -0,0 +1,520 @@ + (2003-2009) + * @author Froxlor team (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Classes + * + */ + +/** + * Class to manage paging system + * + * @package Functions + */ +class Paging +{ + + /** + * Userinfo + * + * @var array + */ + private $userinfo = array(); + + /** + * MySQL-Table + * + * @var string + */ + private $table = ''; + + /** + * Fields with description which should be selectable + * + * @var array + */ + private $fields = array(); + + /** + * Entries per page + * + * @var int + */ + private $entriesperpage = 0; + + /** + * Number of entries of table + * + * @var int + */ + private $entries = 0; + + /** + * Sortorder, asc or desc + * + * @var string + */ + public $sortorder = 'asc'; + + /** + * Sortfield + * + * @var string + */ + public $sortfield = ''; + + /** + * Searchfield + * + * @var string + */ + private $searchfield = ''; + + /** + * Searchtext + * + * @var string + */ + private $searchtext = ''; + + /** + * Pagenumber + * + * @var int + */ + private $pageno = 0; + + /** + * Switch natsorting on/off + * + * @var bool + */ + private $natSorting = false; + + private $limit = 0; + + /** + * Class constructor. + * Loads settings from request or from userdata and saves them to session. + * + * @param + * array userinfo + * @param + * string Name of Table + * @param + * array Fields, in format array( 'fieldname_in_mysql' => 'field_caption' ) + * @param + * int *deprecated* entries per page + * @param + * bool *deprecated* Switch natsorting on/off (global, affects all calls of sort) + * @param int $default_field + * default sorting-field-index + * @param string $default_order + * default sorting order 'asc' or 'desc' + * + */ + public function __construct($userinfo, $table, $fields, $entriesperpage = 0, $natSorting = false, $default_field = 0, $default_order = 'asc', $limit = 0) + { + + // entries per page and natsorting-flag are not + // passed as parameter anymore, because these are + // from the settings anyway + $entriesperpage = \Froxlor\Settings::Get('panel.paging'); + $natSorting = \Froxlor\Settings::Get('panel.natsorting'); + + $this->userinfo = $userinfo; + + if (! is_array($this->userinfo['lastpaging'])) { + $this->userinfo['lastpaging'] = json_decode($this->userinfo['lastpaging'], true); + } + + $this->table = $table; + $this->fields = $fields; + $this->entriesperpage = $entriesperpage; + $this->natSorting = $natSorting; + $checklastpaging = (isset($this->userinfo['lastpaging']['table']) && $this->userinfo['lastpaging']['table'] == $this->table); + $this->userinfo['lastpaging']['table'] = $this->table; + + if (isset($_REQUEST['sortorder']) && (strtolower($_REQUEST['sortorder']) == 'desc' || strtolower($_REQUEST['sortorder']) == 'asc')) { + $this->sortorder = strtolower($_REQUEST['sortorder']); + } else { + + if ($checklastpaging && isset($this->userinfo['lastpaging']['sortorder']) && (strtolower($this->userinfo['lastpaging']['sortorder']) == 'desc' || strtolower($this->userinfo['lastpaging']['sortorder']) == 'asc')) { + $this->sortorder = strtolower($this->userinfo['lastpaging']['sortorder']); + } else { + $this->sortorder = $default_order; + } + } + + $this->userinfo['lastpaging']['sortorder'] = $this->sortorder; + + if (isset($_REQUEST['sortfield']) && isset($fields[$_REQUEST['sortfield']])) { + $this->sortfield = $_REQUEST['sortfield']; + } else { + if ($checklastpaging && isset($this->userinfo['lastpaging']['sortfield']) && isset($fields[$this->userinfo['lastpaging']['sortfield']])) { + $this->sortfield = $this->userinfo['lastpaging']['sortfield']; + } else { + $fieldnames = array_keys($fields); + $this->sortfield = $fieldnames[$default_field]; + } + } + + $this->userinfo['lastpaging']['sortfield'] = $this->sortfield; + + if (isset($_REQUEST['searchfield']) && isset($fields[$_REQUEST['searchfield']])) { + $this->searchfield = $_REQUEST['searchfield']; + } else { + if ($checklastpaging && isset($this->userinfo['lastpaging']['searchfield']) && isset($fields[$this->userinfo['lastpaging']['searchfield']])) { + $this->searchfield = $this->userinfo['lastpaging']['searchfield']; + } else { + $fieldnames = array_keys($fields); + $this->searchfield = $fieldnames[0]; + } + } + + $this->userinfo['lastpaging']['searchfield'] = $this->searchfield; + + if (isset($_REQUEST['searchtext']) && (preg_match('/[-_@\p{L}\p{N}*.]+$/u', $_REQUEST['searchtext']) || $_REQUEST['searchtext'] === '')) { + $this->searchtext = trim($_REQUEST['searchtext']); + } else { + if ($checklastpaging && isset($this->userinfo['lastpaging']['searchtext']) && preg_match('/[-_@\p{L}\p{N}*.]+$/u', $this->userinfo['lastpaging']['searchtext'])) { + $this->searchtext = $this->userinfo['lastpaging']['searchtext']; + } else { + $this->searchtext = ''; + } + } + + $this->userinfo['lastpaging']['searchtext'] = $this->searchtext; + + if (isset($_REQUEST['pageno']) && intval($_REQUEST['pageno']) != 0) { + $this->pageno = intval($_REQUEST['pageno']); + } else { + if ($checklastpaging && isset($this->userinfo['lastpaging']['pageno']) && intval($this->userinfo['lastpaging']['pageno']) != 0) { + $this->pageno = intval($this->userinfo['lastpaging']['pageno']); + } else { + $this->pageno = 1; + } + } + + $this->userinfo['lastpaging']['pageno'] = $this->pageno; + $upd_stmt = \Froxlor\Database\Database::prepare(" + UPDATE `" . TABLE_PANEL_SESSIONS . "` SET + `lastpaging` = :lastpaging + WHERE `hash` = :hash AND `userid` = :userid + AND `ipaddress` = :ipaddr AND `useragent` = :ua + AND `adminsession` = :adminsession + "); + $upd_data = array( + 'lastpaging' => json_encode($this->userinfo['lastpaging']), + 'hash' => $userinfo['hash'], + 'userid' => $userinfo['userid'], + 'ipaddr' => $userinfo['ipaddress'], + 'ua' => $userinfo['useragent'], + 'adminsession' => $userinfo['adminsession'] + ); + \Froxlor\Database\Database::pexecute($upd_stmt, $upd_data); + + $this->limit = $limit; + } + + /** + * Sets number of entries and adjusts pageno if the number of entries doesn't correspond to the pageno. + * + * @param + * int entries + */ + public function setEntries($entries) + { + $this->entries = $entries; + + if (($this->pageno - 1) * $this->entriesperpage > $this->entries) { + $this->pageno = 1; + } + + return true; + } + + /** + * Checks if a row should be displayed or not, used in loops + * + * @param + * int number of row + * @return bool to display or not to display, that's the question + */ + public function checkDisplay($count) + { + $begin = (intval($this->pageno) - 1) * intval($this->entriesperpage); + $end = (intval($this->pageno) * intval($this->entriesperpage)); + return (($count >= $begin && $count < $end) || $this->entriesperpage == 0); + } + + /** + * Returns condition code for sql query + * + * @param + * bool should returned condition code start with WHERE (false) or AND (true)? + * @return string the condition code + */ + public function getSqlWhere($append = false) + { + if ($this->searchtext != '') { + if ($append == true) { + $condition = ' AND '; + } else { + $condition = ' WHERE '; + } + + $searchfield = explode('.', $this->searchfield); + foreach ($searchfield as $id => $field) { + if (substr($field, - 1, 1) != '`') { + $field .= '`'; + } + + if ($field[0] != '`') { + $field = '`' . $field; + } + + $searchfield[$id] = $field; + } + + $searchfield = implode('.', $searchfield); + + $ops = array( + '<', + '>', + '=' + ); + + // check if we use an operator or not + $useOper = 0; + $oper = "="; + if (in_array(substr($this->searchtext, 0, 1), $ops)) { + $useOper = 1; + $oper = substr($this->searchtext, 0, 1); + } + + // check for diskspace and whether searchtext is a number + // in any other case the logical-operators would make no sense + if (strpos($searchfield, 'diskspace') > 0 && is_numeric(substr($this->searchtext, $useOper))) { + // anything with diskspace is *1024 + $searchtext = ((int) substr($this->searchtext, $useOper)) * 1024; + $useOper = 1; + } elseif (strpos($searchfield, 'traffic') > 0 && is_numeric(substr($this->searchtext, $useOper))) { + // anything with traffic is *1024*1024 + $searchtext = ((int) substr($this->searchtext, $useOper)) * 1024 * 1024; + $useOper = 1; + } else { + // any other field + $searchtext = substr($this->searchtext, $useOper); + } + + if ($useOper == 1 && is_numeric(substr($this->searchtext, $useOper))) { + // now as we use >, < or = we use the given operator and not LIKE + $condition .= $searchfield . " " . $oper . " " . \Froxlor\Database\Database::quote($searchtext); + } else { + $searchtext = str_replace('*', '%', $this->searchtext); + // append wildcards if user did not enter any + if (strpos($searchtext, '%') === false) + $searchtext = '%' . $searchtext . '%'; + $condition .= $searchfield . " LIKE " . \Froxlor\Database\Database::quote($searchtext); + } + } else { + $condition = ''; + } + + return $condition; + } + + /** + * Returns "order by"-code for sql query + * + * @param + * bool Switch natsorting on/off (local, affects just this call) + * @return string the "order by"-code + */ + public function getSqlOrderBy($natSorting = null) + { + $sortfield = explode('.', $this->sortfield); + foreach ($sortfield as $id => $field) { + if (substr($field, - 1, 1) != '`') { + $field .= '`'; + } + + if ($field[0] != '`') { + $field = '`' . $field; + } + + $sortfield[$id] = $field; + } + + $sortfield = implode('.', $sortfield); + $sortorder = strtoupper($this->sortorder); + + if ($natSorting == true || ($natSorting === null && $this->natSorting == true)) { + // Acts similar to php's natsort(), found in one comment at http://my.opera.com/cpr/blog/show.dml/160556 + $sortcode = "ORDER BY CONCAT( IF( ASCII( LEFT( " . $sortfield . ", 5 ) ) > 57, + LEFT( " . $sortfield . ", 1 ), 0 ), + IF( ASCII( RIGHT( " . $sortfield . ", 1 ) ) > 57, + LPAD( " . $sortfield . ", 255, '0' ), + LPAD( CONCAT( " . $sortfield . ", '-' ), 255, '0' ) + )) " . $sortorder; + } else { + $sortcode = 'ORDER BY ' . $sortfield . ' ' . $sortorder; + } + + return $sortcode; + } + + /** + * Currently not used + * + * @return string always empty + */ + public function getSqlLimit() + { + if ($this->limit > 0) { + $_offset = ($this->pageno - 1) * $this->limit; + return ' LIMIT ' . $_offset . ',' . $this->limit; + } + /** + * currently not in use + */ + return ''; + } + + /** + * Returns html code for sorting field + * + * @param + * array Language array + * @return string the html sortcode + */ + public function getHtmlSortCode($lng, $break = false) + { + $sortcode = ''; + $fieldoptions = ''; + $orderoptions = ''; + + foreach ($this->fields as $fieldname => $fieldcaption) { + $fieldoptions .= HTML::makeoption($fieldcaption, $fieldname, $this->sortfield, true, true); + } + + $breakorws = ($break ? '
' : ' '); + foreach (array( + 'asc' => $lng['panel']['ascending'], + 'desc' => $lng['panel']['descending'] + ) as $sortordertype => $sortorderdescription) { + $orderoptions .= HTML::makeoption($sortorderdescription, $sortordertype, $this->sortorder, true, true); + } + + eval("\$sortcode =\"" . Template::getTemplate("misc/htmlsortcode", '1') . "\";"); + return $sortcode; + } + + /** + * Returns html code for sorting arrows + * + * @param + * string URL to use as base for links + * @param + * string If set, only this field will be returned + * @return mixed An array or a string (if field is set) of html code of arrows + */ + public function getHtmlArrowCode($baseurl, $field = '') + { + global $theme; + + if ($field != '' && isset($this->fields[$field])) { + $baseurl = htmlspecialchars($baseurl); + $fieldname = htmlspecialchars($field); + eval("\$arrowcode =\"" . Template::getTemplate("misc/htmlarrowcode", '1') . "\";"); + } else { + $baseurl = htmlspecialchars($baseurl); + $arrowcode = array(); + foreach ($this->fields as $fieldname => $fieldcaption) { + $fieldname = htmlspecialchars($fieldname); + eval("\$arrowcode[\$fieldname] =\"" . Template::getTemplate("misc/htmlarrowcode", '1') . "\";"); + } + } + + return $arrowcode; + } + + /** + * Returns html code for searching field + * + * @param + * array Language array + * @return string the html searchcode + */ + public function getHtmlSearchCode($lng) + { + $searchcode = ''; + $fieldoptions = ''; + $searchtext = htmlspecialchars($this->searchtext); + foreach ($this->fields as $fieldname => $fieldcaption) { + $fieldoptions .= HTML::makeoption($fieldcaption, $fieldname, $this->searchfield, true, true); + } + eval("\$searchcode =\"" . Template::getTemplate("misc/htmlsearchcode", '1') . "\";"); + return $searchcode; + } + + /** + * Returns html code for paging + * + * @param + * string URL to use as base for links + * @return string the html pagingcode + */ + public function getHtmlPagingCode($baseurl) + { + if ($this->entriesperpage == 0) { + return ''; + } else { + $pages = intval($this->entries / $this->entriesperpage); + } + + if ($this->entries % $this->entriesperpage != 0) { + $pages ++; + } + + if ($pages > 1) { + + $start = $this->pageno - 4; + if ($start < 1) { + $start = 1; + } + + $stop = $this->pageno + 4; + if ($stop > $pages) { + $stop = $pages; + } + + $pagingcode = '« < '; + for ($i = $start; $i <= $stop; $i ++) { + if ($i != $this->pageno) { + $pagingcode .= ' ' . $i . ' '; + } else { + $pagingcode .= ' ' . $i . ' '; + } + } + $pagingcode .= ' > »'; + } else { + $pagingcode = ''; + } + + return $pagingcode; + } +}