میلاد بهتازگی در دیجیکالا بهعنوان توسعهدهندهی *junior* استخدام شده است. اولین *task* ای که به او واگذار شده، بازنویسی بخش *pagination* وبسایت دیجیاستایل است. از آنجا که میلاد تجربهی انجام این کار را ندارد، از شما میخواهیم تا این بخش را برای او پیادهسازی کنید.
## ساختار پروژه
پروژهی اوّلیه را از [اینجا](https://quera.ir/qbox/download/CxDyLpRy1R/pagination-initial.zip) دانلود کنید. ساختار پروژه بهصورت زیر است:
1. فایل `pagination.tpl`: این فایل شامل قالب *HTML* بخش *pagination* بوده و محتوای آن بهصورت زیر است:
```html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="assets/css/style.css">
<title>Pagination</title>
</head>
<body>
<main class="container">
<ul class="pagination justify-content-center mt-3">
{{ @pages }}
</ul>
</main>
</body>
</html>
```
2. فایل `pagination.php`: شامل دو تابع زیر است:
+ `renderPagination`: این تابع بهترتیب یک رشته حاوی قالب *HTML* ، تعداد مطالب موجود در وبسایت، حداکثر تعداد مطالب در هر صفحه، شمارهی صفحهی فعلی و لینک پایهی صفحات را دریافت میکند. در نهایت، بخش *pagination* را بهصورت یک رشته برمیگرداند.
+ `getPaginationButtons`: این تابع بهترتیب تعداد مطالب موجود در وبسایت، حداکثر تعداد مطالب در هر صفحه و شمارهی صفحهی فعلی را دریافت کرده و آرایهای شامل دکمهها جهت نمایش در بخش *pagination* را برمیگرداند. هر دکمه یک آرایهی *associative* است که شامل دو کلید `text` و `number` است. مقدار کلید `text` برای دکمهی رفتن به صفحهی قبلی `prev` و برای دکمهی رفتن به صفحهی بعدی `next` است. همچنین، مقدار کلید `text` برای دکمهی `...` همان `...` است. مقدار کلید `number` بیانگر شمارهی صفحهی موجود در لینک دکمه است؛ برای مثال اگر ۴ صفحه داشته باشیم و در حال حاضر در صفحهی ۳ باشیم، مقدار کلید `number` برای دکمههای `prev` و `next` بهترتیب برابر با `2` و `4` خواهد بود. بدیهی است که مقدار کلید `number` برای سایر دکمهها (بهجز دکمهی `...`) باید برابر با مقدار کلید `text` باشد.
**توجه:** دکمهی `...` نباید کلید `number` را داشته باشد.
محتویات فایل `pagination.php` بهصورت زیر است:
```php
<?php
function getPaginationButtons($total_items, $per_page, $current_page)
{
// Implement getPaginationButtons function here
}
function renderPagination($pagination_template, $total_items, $per_page, $current_page, $base_url)
{
$pages = getPaginationButtons($total_items, $per_page, $current_page);
$html = '';
foreach ($pages as $page) {
$page['text'] = str_replace(['prev', 'next'], ['«', '»'], $page['text']);
if (in_array($page['text'], ['«', '...', '»'])) {
$html .= '<li class="page-item">
<a class="page-link" href="' . (isset($page['number']) ? $base_url . $page['number'] : '#') . '">
<span aria-hidden="true">' . $page['text'] . '</span>
</a>
</li>';
} else {
$html .= '<li class="page-item' . ($page['number'] == $current_page ? ' active' : '')
. '"><a class="page-link" href="' . $base_url . $page['number'] . '">'
. $page['number'] . '</a></li>';
}
}
return str_replace('{{ @pages }}', $html, $pagination_template);
}
```
قوانین صفحهبندی بهشرح زیر هستند:
+ صفحات اول و آخر باید از طریق همهی صفحات در دسترس باشند.
+ دو صفحهی قبلی و دو صفحهی بعدی هر صفحه باید در دسترس باشند.
+ صفحاتی که فاصلهشان از صفحهی فعلی بزرگتر یا مساوی ۳ است با یک دکمهی `...` نمایش داده میشوند.
+ اگر فاصلهی دو صفحه از یکدیگر ۲ واحد باشد، به جای دکمهی `...` دکمهی شمارهی صفحهی بین آنها قرار میگیرد؛ برای مثال، بین دکمههای ۵ و ۷ هیچگاه دکمهی `...` نمیآید.
+ دکمهی `prev` باید در صورتی نمایش داده شود که شمارهی صفحهی فعلی ۱ نباشد.
+ دکمهی `next` باید در صورتی نمایش داده شود که شمارهی صفحهی فعلی برابر با تعداد صفحات نباشد.
**توجه:** ترتیب آرایههای خروجی تابع `getPaginationButtons` باید بهصورت زیر باشد:
+ دکمهی `prev` (در صورت وجود)
+ دکمهی شمارهی صفحات با ترتیب صعودی (میتواند شامل دکمهی `...` نیز باشد.)
+ دکمهی `next` (در صورت وجود)
### مثال ۱:
```php
<?php
require 'pagination.php';
getPaginationButtons(56, 5, 7);
/**
[
["text" => "prev", "number" => 6],
["text" => "1", "number" => 1],
["text" => "..."],
["text" => "5", "number" => 5],
["text" => "6", "number" => 6],
["text" => "7", "number" => 7],
["text" => "8", "number" => 8],
["text" => "9", "number" => 9],
["text" => "..."],
["text" => "12", "number" => 12],
["text" => "next", "number" => 8]
]
*/
$pagination_template = file_get_contents('pagination.tpl');
echo renderPagination($pagination_template, 56, 5, 7, 'index.php?page=');
```
خروجی مورد انتظار:
![pagination-1](https://quera.ir/qbox/view/hLTJofxmjG/pagination-1.png)
### مثال ۲:
```php
<?php
require 'pagination.php';
getPaginationButtons(14, 4, 1);
/**
[
["text" => "1", "number" => 1],
["text" => "2", "number" => 2],
["text" => "3", "number" => 3],
["text" => "4", "number" => 4],
["text" => "next", "number" => 2]
]
*/
$pagination_template = file_get_contents('pagination.tpl');
echo renderPagination($pagination_template, 14, 4, 1, 'index.php?page=');
```
خروجی مورد انتظار:
![pagination-2](https://quera.ir/qbox/view/ht7Gee4mGq/pagination-2.png)
### مثال ۳:
```php
<?php
require 'pagination.php';
getPaginationButtons(40, 10, 4);
/**
[
["text" => "prev", "number" => 3],
["text" => "1", "number" => 1],
["text" => "2", "number" => 2],
["text" => "3", "number" => 3],
["text" => "4", "number" => 4]
]
*/
$pagination_template = file_get_contents('pagination.tpl');
echo renderPagination($pagination_template, 40, 10, 4, 'index.php?page=');
```
خروجی مورد انتظار:
![pagination-3](https://quera.ir/qbox/view/w8iUmEoyVe/pagination-3.png)
### مثال ۴:
```php
<?php
require 'pagination.php';
getPaginationButtons(24, 3, 6);
/**
[
["text" => "prev", "number" => 5],
["text" => "1", "number" => 1],
["text" => "..."],
["text" => "4", "number" => 4],
["text" => "5", "number" => 5],
["text" => "6", "number" => 6],
["text" => "7", "number" => 7],
["text" => "8", "number" => 8],
["text" => "next", "number" => 7]
]
*/
$pagination_template = file_get_contents('pagination.tpl');
echo renderPagination($pagination_template, 24, 3, 6, 'index.php?page=');
```
خروجی مورد انتظار:
![pagination-4](https://quera.ir/qbox/view/69h0FIGDsr/pagination-4.png.png)
### مثال ۵:
```php
<?php
require 'pagination.php';
getPaginationButtons(7, 1, 2);
/**
[
["text" => "prev", "number" => 1],
["text" => "1", "number" => 1],
["text" => "2", "number" => 2],
["text" => "3", "number" => 3],
["text" => "4", "number" => 4],
["text" => "..."],
["text" => "7", "number" => 7],
["text" => "next", "number" => 3]
]
*/
$pagination_template = file_get_contents('pagination.tpl');
echo renderPagination($pagination_template, 7, 1, 2, 'index.php?page=');
```
خروجی مورد انتظار:
![pagination-5](https://quera.ir/qbox/view/Qk9xkWIjqR/pagination-5.png)
3. فایل `index.php`: این فایل توابع موجود در فایل `pagination.php` را فراخوانی کرده و از طریق آن میتوان خروجی بخش *pagination* را مشاهده کرد. محتوای آن بهصورت زیر است:
```php
<?php
require 'pagination.php';
$pagination_template = file_get_contents('pagination.tpl');
echo renderPagination($pagination_template, 7 * 5, 5, 2, 'index.php?page=');
```
## آنچه باید آپلود کنید
پس از پیادهسازی تابع `getPaginationButtons`، فایل `pagination.php` را آپلود کنید.
---
<details class="blue">
<summary>راهنمایی ۱</summary>
تعداد صفحات برابر خواهد بود با $\lceil\frac{\$total\_items}{\$per\_page}\rceil$:
```php
$pages_count = ceil($total_items/ $per_page);
```
</details>
<details class="blue">
<summary>راهنمایی ۲</summary>
آرایهای برای ذخیرهسازی دکمهها در نظر میگیریم:
```php
$buttons = [];
```
اگر تعداد صفحات بیشتر از ۱ باشد، دکمهی `prev` شمارهی `$current_page - 1` را اضافه میکنیم:
```php
if ($current_page > 1) {
$buttons[] = ['text' => 'prev', 'number' => $current_page - 1];
}
```
پس از اضافه کردن دکمههای شماره و `...` (در صورت نیاز)، اگر تعداد صفحات بیشتر از شمارهی صفحهی فعلی باشد، دکمهی `next` با شمارهی `$current_page + 1` را اضافه میکنیم:
```php
if ($current_page < $pages_count) {
$buttons[] = ['text' => 'next', 'number' => $current_page + 1];
}
```
</details>
<details class="blue">
<summary>راهنمایی ۳</summary>
میدانیم حداکثر دو دکمهی `...` در بین دکمهها موجود خواهند بود که یکی از این دکمهها در بین دکمههای سمت چپ دکمهی صفحهی فعلی و دیگری در بین دکمههای سمت راست دکمهی صفحهی فعلی خواهد بود. دو *flag* برای این دو دکمه در نظر میگیریم که هرگاه این دکمهها درج شوند، *flag* شان `true` میشود.
```php
$leftDots = false;
$rightDots = false;
```
پیمایش را از شمارهی ۱ تا تعداد صفحات انجام میدهیم. اگر مقدار شمارهی فعلی ۱ باشد، یا اختلاف آن با شمارهی صفحهی فعلی کمتر از ۳ باشد، یا مقدار شمارندهی فعلی برابر با تعداد صفحات باشد، دکمهای با مقدار شمارنده درج میکنیم.
در غیر اینصورت، اگر مقدار شمارنده کوچکتر از شمارهی صفحهی فعلی باشد و `$leftDots` برابر با `false` باشد، یک دکمهی `...` درج کرده و `$leftDots` را `true` میکنیم.
در غیر اینصورت، اگر مقدار شمارنده بزرگتر از شمارهی صفحهی فعلی باشد و `$rightDots` برابر با `false` باشد، یک دکمهی `...` درج کرده و `$rightDots` را `true` میکنیم.
کد این بخش بهصورت زیر خواهد بود:
```php
for ($i = 1; $i <= $pages_count; $i++) {
if ($i == 1 || abs($current_page - $i) <= 2 || $i == $pages_count) {
$buttons[] = ['text' => $i, 'number' => $i];
}
elseif ($i < $current_page && !$rightDots) {
$buttons[] = ['text' => '...'];
$rightDots = true;
}
elseif ($i > $current_page && !$leftDots) {
$buttons[] = ['text' => '...'];
$leftDots = true;
}
}
```
</details>
ارسال پاسخ برای این سؤال
در حال حاضر شما دسترسی ندارید.