You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
9.1 KiB
289 lines
9.1 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Modified from:
|
|
* @link https://code.tutsplus.com/tutorials/how-to-paginate-data-with-php--net-2928
|
|
*/
|
|
|
|
namespace IOcornerstone\Framework\Database;
|
|
|
|
class Paginate
|
|
{
|
|
|
|
private $_conn;
|
|
private int $_limit;
|
|
private int $_page;
|
|
private $_query;
|
|
private $_total;
|
|
private $_url;
|
|
private $_url_limit;
|
|
private $_url_page;
|
|
public $maxLimit = 500;
|
|
|
|
/*
|
|
* Query needs to be string for MySQL and array for MonogDB
|
|
*/
|
|
|
|
public function __construct($conn, string|array $query, string $dbType = "mysql")
|
|
{
|
|
$this->_conn = $conn;
|
|
$this->_query = $query;
|
|
|
|
if ($dbType === "mysql") {
|
|
$rs = $this->_conn->query($this->_query);
|
|
$this->_total = $rs->rowCount();
|
|
}
|
|
}
|
|
|
|
private function setLimit(int $limit = 10): int
|
|
{
|
|
if ($limit < 1) {
|
|
return 10;
|
|
}
|
|
return ($limit > $this->maxLimit) ? $this->maxLimit : $limit;
|
|
}
|
|
|
|
private function setPage(int $page = 1): int
|
|
{
|
|
return ($page < 1) ? 1 : $page;
|
|
}
|
|
|
|
public function mongoGetData(int $limit = 10, int $page = 1, array $options = [])
|
|
{
|
|
$this->_limit = $this->setLimit($limit); // Number of items per page
|
|
$this->_page = $this->setPage($page); // The current page number
|
|
|
|
$skip = (($this->_page - 1) * $this->_limit);
|
|
|
|
if ($this->_limit === 0) {
|
|
$db_options = $options;
|
|
} else {
|
|
$limits = ['limit' => $this->_limit, 'skip' => $skip];
|
|
$db_options = array_merge($limits, $options);
|
|
}
|
|
|
|
// NOTE _query is the WHERE condition as an array
|
|
$collection = $this->_conn;
|
|
$documents = $collection->find($this->_query, $db_options);
|
|
|
|
// Calculate the total number of documents in the collection
|
|
$this->_total = $collection->countDocuments($this->_query);
|
|
|
|
$result = new \stdClass();
|
|
$result->page = $this->_page;
|
|
$result->limit = $this->_limit;
|
|
$result->total = $this->_total;
|
|
$result->data = $documents;
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function getData(int $limit = 10, int $page = 1)
|
|
{
|
|
$this->_limit = $this->setLimit($limit);
|
|
$this->_page = $this->setPage($page);
|
|
|
|
if ($this->_limit === 0) {
|
|
$query = $this->_query;
|
|
} else {
|
|
$query = $this->_query . " LIMIT " . (($this->_page - 1) * $this->_limit) . ", $this->_limit";
|
|
}
|
|
$rs = $this->_conn->query($query);
|
|
|
|
$result = new \stdClass();
|
|
$result->page = $this->_page;
|
|
$result->limit = $this->_limit;
|
|
$result->total = $this->_total;
|
|
$result->rs = $rs;
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function useHashRoutes(string $url): void
|
|
{
|
|
$this->_url = $url;
|
|
$this->_url_limit = "/";
|
|
$this->_url_page = "/";
|
|
}
|
|
|
|
public function useGetRoutes(string $url = ""): void
|
|
{
|
|
$this->_url = $url;
|
|
$this->_url_limit = "?limit=";
|
|
$this->_url_page = "&page=";
|
|
}
|
|
|
|
private function do_href(int $limit, int $page): string
|
|
{
|
|
$queryParmas = $_GET;
|
|
unset($queryParmas['limit']);
|
|
unset($queryParmas['page']);
|
|
$q = http_build_query($queryParmas);
|
|
$querySeperator = (str_contains($this->_url_limit, "?")) ? "&" : "?";
|
|
$querySeperator = (empty($q)) ? "" : $querySeperator;
|
|
return 'href="' . $this->_url . $this->_url_limit . $limit . $this->_url_page . $page . $querySeperator . $q . '"';
|
|
}
|
|
|
|
public function createLinks(int $links = 7, string $list_class = "ui pagination menu", string $item = "item"): string
|
|
{
|
|
$last = ceil($this->_total / $this->_limit);
|
|
|
|
if ($this->_limit === 0 || $last < 2) {
|
|
return '';
|
|
}
|
|
|
|
$start = (($this->_page - $links) > 0) ? $this->_page - $links : 1;
|
|
$end = (($this->_page + $links) < $last) ? $this->_page + $links : $last;
|
|
|
|
$html = '<div class="' . $list_class . '">';
|
|
|
|
$class = ($this->_page == 1) ? "disabled" : "";
|
|
$item = " " . $item;
|
|
|
|
$html .= '<a class="' . $class . $item . '" ' . $this->do_href($this->_limit, $this->_page - 1) . '>«</a>';
|
|
|
|
if ($start > 1) {
|
|
$html .= '<a class="' . $item . '" ' . $this->do_href($this->_limit, 1) . '>1</a>';
|
|
$html .= '<div class="disabled' . $item . '"><span>...</span></div>';
|
|
}
|
|
|
|
for ($i = $start; $i <= $end; $i++) {
|
|
$class = ($this->_page == $i) ? "active" : "";
|
|
$html .= '<a class="' . $class . $item . '" ' . $this->do_href($this->_limit, $i) . '>' . $i . '</a>';
|
|
}
|
|
|
|
if ($end < $last) {
|
|
$html .= '<div class="disabled' . $item . '"><span>...</span></div>';
|
|
$html .= '<a class="' . $class . $item . '" ' . $this->do_href($this->_limit, $last) . '>' . $last . '</a>';
|
|
}
|
|
|
|
$class = ($this->_page == $last) ? "disabled" : "";
|
|
$html .= '<a class="' . $class . $item . '" ' . $this->do_href($this->_limit, $this->_page + 1) . '>»</a>';
|
|
|
|
$html .= '</div>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
public function createJumpMenuWithLinks(int $links = 7, string $label = "Jump to ", string $end_label = " page.", string $item = "item"): string
|
|
{
|
|
if ($this->_limit === 0) {
|
|
return '';
|
|
}
|
|
|
|
$last = ceil($this->_total / $this->_limit);
|
|
|
|
$start = (($this->_page - $links) > 0) ? $this->_page - $links : 1;
|
|
$end = (($this->_page + $links) < $last) ? $this->_page + $links : $last;
|
|
|
|
// Prev. Page
|
|
$class = ($this->_page == 1) ? "disabled " : "";
|
|
$item = " " . $item;
|
|
$href = ($this->_page == 1) ? "" : $this->do_href($this->_limit, $this->_page - 1);
|
|
$html .= '<a class="' . $class . $item . '" ' . $href . '>«</a>';
|
|
|
|
$html .= $this->createJumpMenu();
|
|
|
|
// Next Page
|
|
$class = ($this->_page == $last) ? "disabled " : "";
|
|
$href = ($this->_page == $last) ? "" : $this->do_href($this->_limit, $this->_page + 1);
|
|
$html .= '<a class="' . $class . $item . '" ' . $href . '>»</a>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
public function createJumpMenu(string $label = "Jump to ", string $end_label = " page.", string $item = "item"): string
|
|
{
|
|
$last = ceil($this->_total / $this->_limit);
|
|
$option = '';
|
|
for ($i = 1; $i <= $last; $i++) {
|
|
$option .= ($i == $this->_page) ? "<option value=\"{$i}\" selected>Page {$i}</option>\n" : "<option value=\"{$i}\">Page {$i}</option>\n";
|
|
}
|
|
return "<label>{$label}<select class=\"{$item}\" onchange=\"window.location='" . $this->_url . $this->_url_limit . $this->_limit . $this->_url_page . "'+this[this.selectedIndex].value;return false;\">"
|
|
. "{$option}</select>"
|
|
. "{$end_label}</label>\n";
|
|
}
|
|
|
|
public function createItemsPerPage(string $label = "Items ", string $end_label = " per page.", string $item = "item"): string
|
|
{
|
|
$items = '';
|
|
$ipp_array = array(3, 6, 12, 24, 50, 100);
|
|
$found = false;
|
|
foreach ($ipp_array as $ipp_opt) {
|
|
if ($ipp_opt == $this->_limit) {
|
|
$found = true;
|
|
}
|
|
$items .= ($ipp_opt == $this->_limit) ? "<option selected value=\"{$ipp_opt}\">{$ipp_opt}</option>\n" : "<option value=\"{$ipp_opt}\">{$ipp_opt}</option>\n";
|
|
}
|
|
|
|
if ($found === false) {
|
|
$items = "<option selected value=\"{$this->_limit}\">{$this->_limit}</option>\n" . $items;
|
|
}
|
|
|
|
$my_page = str_replace("&", "?", $this->_url_page);
|
|
$my_limit = str_replace("?", "&", $this->_url_limit);
|
|
|
|
return "<label>{$label}<select class=\"{$item}\" onchange=\"window.location='" . $my_page . "1" . $my_limit . "'+this[this.selectedIndex].value;return false;\">{$items}</select>"
|
|
. "{$end_label}</label>\n";
|
|
}
|
|
|
|
public function getCSS(): string
|
|
{
|
|
return ".pagination a {
|
|
color: #333;
|
|
padding: 2px 20px;
|
|
line-height: 1;
|
|
font-size: 14px;
|
|
text-decoration: none;
|
|
border-radius: 6px;
|
|
border: 1px solid #ddd;
|
|
background: #fff;
|
|
box-shadow: 0 1px 3px rgba(0,0,0,.1);
|
|
transition: all .2s ease;
|
|
}
|
|
.pagination a:hover:not(.active) {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 2px 6px rgba(0,0,0,.15);
|
|
}
|
|
.pagination a.active {
|
|
background: #4CAF50;
|
|
color: white;
|
|
border-color: #4CAF50;
|
|
}
|
|
.pagination .disabled {
|
|
display: inline-block;
|
|
padding: 4px 12px;
|
|
color: #999;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
background: #f8f8f8;
|
|
cursor: not-allowed;
|
|
pointer-events: none;
|
|
opacity: 0.6;
|
|
}
|
|
div.pagination.menu {
|
|
padding-top: 10px;
|
|
}";
|
|
}
|
|
}
|
|
|
|
/*
|
|
* mongo db
|
|
$limit = $_GET['limit'] ?? 18;
|
|
$page = $_GET['page'] ?? 1;
|
|
$url = "#pages/bill";
|
|
$query = [ 'user_id' => (string) $user_id ];
|
|
$mongo_options = [ 'projection' => [ 'billing' => 1 ]];
|
|
|
|
$pag = new Paginate($collection, $query, "mongodb");
|
|
$r = $pag->mongoGetData($limit, $page, $mongo_options);
|
|
$pag->useHashRoutes($url);
|
|
|
|
foreach ($r->data as $bill) {
|
|
echo $bill;
|
|
}
|
|
|
|
echo $pag->createLinks();
|
|
*/ |