From 35e811312c24564c14aebebfd457a597f51b90fa Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Sat, 18 May 2024 14:55:10 +0400 Subject: [PATCH] fix bug in pagination behavior, refactor bug fixed: on page X, products from previous pages should not be displayed --- src/controllers/Shop.php | 65 +++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/src/controllers/Shop.php b/src/controllers/Shop.php index b3eb94b..fc652e6 100644 --- a/src/controllers/Shop.php +++ b/src/controllers/Shop.php @@ -17,6 +17,7 @@ class Shop use Controller; private array $data; + private static int $MAX_PRODUCTS_PER_PAGE = 4; /** * Check if a product matches the category filter (if any) @@ -71,7 +72,7 @@ private function sort_product(Product $a, Product $b): int return 0; } - // sort by date + // sort by descending date if ($_GET['sort'] === 'newest') { return ($a->getCreatedDate() > $b->getCreatedDate()) ? -1 : 1; } @@ -99,6 +100,46 @@ private function sort_product(Product $a, Product $b): int return 0; // no sorting if invalid sorting option } + /** + * @return Product[] Array of products which match filters (excluding pagination) and sorting applied by user + */ + public function getMatchingProducts(): array + { + // Fetch all products from the database + $all_products = Product::getAll(); + + // Apply filtering based on search keyword and category (existing functionality) + $filtered_products = array_filter($all_products, array($this, "match_keyword")); + $filtered_products = array_filter($filtered_products, array($this, "match_category")); + + // Sort the filtered products (existing functionality) + usort($filtered_products, array($this, "sort_product")); + + return $filtered_products; + } + + /** + * @return int Page number on shop page. Defaults to 1. + */ + public function getPageNumber(): int + { + return (int)($_GET['page'] ?? 1); + } + + /** + * @param $products + * @return array Products which should be displayed on current page + */ + public function applyPagination($products): array + { + // Slice the products based on pagination + return array_slice( + $products, + ($this->getPageNumber() - 1) * Shop::$MAX_PRODUCTS_PER_PAGE, + Shop::$MAX_PRODUCTS_PER_PAGE + ); + } + public function index(): void { // check if URL follows format /shop/products/ @@ -115,24 +156,11 @@ public function index(): void return; } - // Retrieve the page number from the URL query parameters - $page = $_GET['page'] ?? 1; - $perPage = (int) $page * 4; // Number of products per page - - // Fetch all products from the database - $all_products = Product::getAll(); - - $this->data['all_products'] = $all_products; - - // Apply filtering based on search keyword and category (existing functionality) - $filtered_products = array_filter($all_products, array($this, "match_keyword")); - $filtered_products = array_filter($filtered_products, array($this, "match_category")); - - // Sort the filtered products (existing functionality) - usort($filtered_products, array($this, "sort_product")); + // get all products that match user criteria + $filtered_products = $this->getMatchingProducts(); // Slice the products based on pagination - $paginated_products = array_slice($filtered_products, 0, $perPage); + $paginated_products = $this->applyPagination($filtered_products); // Initialize view variables (existing functionality) $this->data['products'] = $paginated_products; @@ -140,7 +168,8 @@ public function index(): void $this->data['categories'] = Product::getCategories(); $this->data['sort_option'] = $_GET['sort'] ?? ""; $this->data['selected_categories'] = $_GET['categories'] ?? []; - $this->data['page'] = $page; + $this->data['page'] = $this->getPageNumber(); + $this->data['totalPages'] = ceil(count($filtered_products) / Shop::$MAX_PRODUCTS_PER_PAGE); // Render the view with pagination information $this->view(