Skip to content

Commit 15ffc85

Browse files
committed
Add pagination to news page
1 parent 00e8bad commit 15ffc85

File tree

5 files changed

+174
-17
lines changed

5 files changed

+174
-17
lines changed

controllers/News.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use \BNETDocs\Libraries\Controller;
77
use \BNETDocs\Libraries\Exceptions\UnspecifiedViewException;
88
use \BNETDocs\Libraries\NewsPost;
9+
use \BNETDocs\Libraries\Pagination;
910
use \BNETDocs\Libraries\Router;
1011
use \BNETDocs\Libraries\User;
1112
use \BNETDocs\Libraries\UserSession;
@@ -14,9 +15,12 @@
1415
use \BNETDocs\Views\NewsRSS as NewsRSSView;
1516
use \DateTime;
1617
use \DateTimeZone;
18+
use \OutOfBoundsException;
1719

1820
class News extends Controller {
1921

22+
const NEWS_PER_PAGE = 5;
23+
2024
public function run(Router &$router) {
2125
switch ($router->getRequestPathExtension()) {
2226
case "htm": case "html": case "":
@@ -40,7 +44,9 @@ public function run(Router &$router) {
4044
User::OPTION_ACL_NEWS_DELETE
4145
)
4246
);
43-
$this->getNews($model);
47+
$query = $router->getRequestQueryArray();
48+
$page = (isset($query["page"]) ? ((int) $query["page"]) - 1 : null);
49+
$this->getNews($model, (!$view instanceof NewsRSSView), $page);
4450
ob_start();
4551
$view->render($model);
4652
$router->setResponseCode(200);
@@ -50,7 +56,7 @@ public function run(Router &$router) {
5056
ob_end_clean();
5157
}
5258

53-
protected function getNews(NewsModel &$model) {
59+
protected function getNews(NewsModel &$model, $paginate, $page) {
5460
$model->news_posts = NewsPost::getAllNews(true);
5561

5662
// Remove news posts that are not published
@@ -64,6 +70,20 @@ protected function getNews(NewsModel &$model) {
6470
--$i;
6571
}
6672
}
73+
74+
if ($paginate) {
75+
try {
76+
$model->pagination = new Pagination(
77+
$model->news_posts, $page, self::NEWS_PER_PAGE
78+
);
79+
$model->news_posts = $model->pagination->getPage();
80+
} catch (OutOfBoundsException $e) {
81+
$model->news_posts = null;
82+
}
83+
} else {
84+
$model->pagination = null;
85+
}
86+
6787
}
6888

6989
}

libraries/Pagination.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
namespace BNETDocs\Libraries;
4+
5+
use \OutOfBoundsException;
6+
use \Traversable;
7+
use \UnexpectedValueException;
8+
9+
class Pagination {
10+
11+
private $dataset;
12+
private $limit;
13+
private $page;
14+
15+
public function __construct($dataset, $page, $limit) {
16+
$this->dataset = $dataset;
17+
$this->limit = $limit;
18+
$this->page = $page;
19+
20+
if (!$this->dataset instanceof Traversable && !is_array($this->dataset))
21+
throw new UnexpectedValueException("Dataset is not traversable");
22+
if ($this->limit < 1)
23+
throw new OutOfBoundsException("Limit is less than one");
24+
if ($this->page < 0 || $this->page > $this->pageCount())
25+
throw new OutOfBoundsException("Page is out of bounds");
26+
}
27+
28+
public function currentPage() {
29+
return $this->page;
30+
}
31+
32+
public function getPage() {
33+
$lbound = $this->page * $this->limit;
34+
$ubound = $lbound + $this->limit;
35+
$set = [];
36+
$keys = array_keys($this->dataset);
37+
$size = count($keys);
38+
39+
if ($ubound > $size) $ubound = $size;
40+
41+
for ($i = $lbound; $i < $ubound; ++$i) {
42+
$set[] = $this->dataset[$keys[$i]];
43+
}
44+
45+
return $set;
46+
}
47+
48+
public function nextPage() {
49+
if ($this->page >= $this->pageCount())
50+
throw new OutOfBoundsException("Current page reached upper bound");
51+
$this->page += 1;
52+
return $this->page;
53+
}
54+
55+
public function pageCount() {
56+
return ceil(count(array_keys($this->dataset)) / $this->limit);
57+
}
58+
59+
public function previousPage() {
60+
if ($this->page <= 0)
61+
throw new OutOfBoundsException("Current page reached lower bound");
62+
$this->page -= 1;
63+
return $this->page;
64+
}
65+
66+
public function setPage($page) {
67+
if ($page < 0 || $page > $this->pageCount())
68+
throw new OutOfBoundsException("Page is out of bounds");
69+
$this->page = $page;
70+
return $this->page;
71+
}
72+
73+
}

models/News.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ class News extends Model {
88

99
public $acl_allowed;
1010
public $news_posts;
11+
public $pagination;
1112
public $user;
1213
public $user_session;
1314

1415
public function __construct() {
1516
parent::__construct();
1617
$this->acl_allowed = null;
1718
$this->news_posts = [];
19+
$this->pagination = null;
1820
$this->user = null;
1921
$this->user_session = null;
2022
}

static/a/main.css

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,26 @@ body > main > article > footer {
182182
min-height: 20px;
183183
padding: 10px;
184184
}
185+
main > p.pagination {
186+
text-align: center;
187+
margin-left: 232px;
188+
}
189+
p.pagination > a {
190+
background-color: rgba(128,128,128,0.4);
191+
border: 0px;
192+
-moz-box-sizing: border-box;
193+
box-sizing: border-box;
194+
display: inline-block;
195+
color: inherit;
196+
cursor: pointer;
197+
margin: 1px 0px;
198+
outline: none;
199+
padding: 4px 8px;
200+
text-align: center;
201+
}
202+
p.pagination > a.active {
203+
background-color: rgba(128,128,128,0.8);
204+
}
185205
body > footer {
186206
box-sizing: border-box;
187207
color: rgba(224,224,224,0.3);

templates/News.phtml

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,36 @@ $this->opengraph->attach(new Pair("url", "/news"));
1414
$this->additional_css[] = "/a/news.css";
1515
require("./header.inc.phtml");
1616

17-
$avatars = [];
18-
$getAvatar = function(&$avatars, $user_id) {
19-
if (isset($avatars[$user_id])) {
20-
return $avatars[$user_id];
21-
}
22-
$avatars[$user_id] = new Gravatar((new User($user_id))->getEmail());
23-
return $avatars[$user_id];
24-
};
17+
$news_posts = $this->getContext()->news_posts;
18+
$pagination = $this->getContext()->pagination;
2519

26-
$users = [];
27-
foreach ($this->context->news_posts as $news_post) {
28-
$url = Common::relativeUrlToAbsolute("/news/" . urlencode($news_post->getId()));
29-
$url .= "/" . Common::sanitizeForUrl($news_post->getTitle(), true);
30-
$user_id = $news_post->getUserId();
31-
$avatar = "https:" . $getAvatar($avatars, $user_id)->getUrl(22, "identicon");
32-
if (!isset($users[$user_id])) $users[$user_id] = new User($user_id);
20+
if (is_null($news_posts) || empty($news_posts)) {
3321
?>
22+
<article>
23+
<header class="red">No News Found</header>
24+
<section class="red">
25+
<p>There are no news posts to view at this time.</p>
26+
</section>
27+
</article>
28+
<?php
29+
} else {
30+
31+
$avatars = [];
32+
$getAvatar = function(&$avatars, $user_id) {
33+
if (isset($avatars[$user_id])) {
34+
return $avatars[$user_id];
35+
}
36+
$avatars[$user_id] = new Gravatar((new User($user_id))->getEmail());
37+
return $avatars[$user_id];
38+
};
39+
40+
$users = [];
41+
foreach ($this->getContext()->news_posts as $news_post) {
42+
$url = Common::relativeUrlToAbsolute("/news/" . urlencode($news_post->getId()));
43+
$url .= "/" . Common::sanitizeForUrl($news_post->getTitle(), true);
44+
$user_id = $news_post->getUserId();
45+
$avatar = "https:" . $getAvatar($avatars, $user_id)->getUrl(22, "identicon");
46+
if (!isset($users[$user_id])) $users[$user_id] = new User($user_id); ?>
3447
<article>
3548
<a href="https://plus.google.com/share?url=<?php echo urlencode($url); ?>" rel="external" data-popup="1"><img class="social-btn float-right" src="<?php echo Common::relativeUrlToAbsolute("/a/social-gplus-24px.png"); ?>"/></a>
3649
<a href="https://twitter.com/share?text=<?php echo urlencode($news_post->getTitle()); ?>&amp;url=<?php echo urlencode($url); ?>" rel="external" data-popup="1"><img class="social-btn float-right" src="<?php echo Common::relativeUrlToAbsolute("/a/social-twitter-24px.png"); ?>"/></a>
@@ -46,4 +59,33 @@ foreach ($this->context->news_posts as $news_post) {
4659
</footer>
4760
</article>
4861
<?php }
62+
}
63+
if ($pagination) {
64+
$page_current = $pagination->currentPage();
65+
$page_count = $pagination->pageCount();
66+
$page_prev = ($page_current > 0 ? $page_current + 0 : false);
67+
$page_next = ($page_current + 1 < $page_count ? $page_current + 2 : false);
68+
?>
69+
<p class="pagination">
70+
<?php
71+
if ($page_prev) { ?>
72+
<a href="<?php echo Common::relativeUrlToAbsolute(
73+
"/news?page=" . urlencode($page_prev)
74+
); ?>">&lt;</a>
75+
<?php
76+
}
77+
for ($i = 1; $i <= $page_count; ++$i) {
78+
?>
79+
<a<?php if ($i - 1 == $page_current) { ?> class="active"<?php }
80+
?> href="<?php echo Common::relativeUrlToAbsolute(
81+
"/news?page=" . urlencode($i)
82+
); ?>"><?php echo $i; ?></a>
83+
<?php }
84+
if ($page_next) { ?>
85+
<a href="<?php echo Common::relativeUrlToAbsolute(
86+
"/news?page=" . urlencode($page_next)
87+
); ?>">&gt;</a>
88+
<?php } ?>
89+
</p>
90+
<?php }
4991
require("./footer.inc.phtml"); ?>

0 commit comments

Comments
 (0)