Merge pull request #3158 from Krymonota/fix-veoh-privacy-policy-link-text
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / system / template / plugin / PagesFunctionTemplatePlugin.class.php
1 <?php
2 namespace wcf\system\template\plugin;
3 use wcf\system\exception\SystemException;
4 use wcf\system\request\LinkHandler;
5 use wcf\system\template\TemplateEngine;
6 use wcf\system\WCF;
7 use wcf\util\StringUtil;
8
9 /**
10 * Template function plugin which generates sliding pagers.
11 *
12 * Usage:
13 * {pages pages=10 link='page-%d.html'}
14 * {pages page=8 pages=10 link='page-%d.html'}
15 *
16 * assign to variable 'output'; do not print:
17 * {pages page=8 pages=10 link='page-%d.html' assign='output'}
18 *
19 * assign to variable 'output' and do print also:
20 * {pages page=8 pages=10 link='page-%d.html' assign='output' print=true}
21 *
22 * @author Marcel Werk
23 * @copyright 2001-2017 WoltLab GmbH
24 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
25 * @package WoltLabSuite\Core\System\Template\Plugin
26 */
27 class PagesFunctionTemplatePlugin implements IFunctionTemplatePlugin {
28 const SHOW_LINKS = 9;
29
30 /**
31 * CSS class name for <nav> element
32 * @var string
33 */
34 protected $cssClassName = 'pagination';
35
36 /**
37 * Inserts the page number into the link.
38 *
39 * @param string $link
40 * @param integer $pageNo
41 * @return string final link
42 */
43 protected static function insertPageNumber($link, $pageNo) {
44 $startPos = mb_strpos($link, '%d');
45 if ($startPos !== null) $link = mb_substr($link, 0, $startPos) . $pageNo . mb_substr($link, $startPos + 2);
46 return $link;
47 }
48
49 /**
50 * Generates HTML code for a link.
51 *
52 * @param string $link
53 * @param integer $pageNo
54 * @param integer $activePage
55 * @param integer $pages
56 * @return string
57 */
58 protected function makeLink($link, $pageNo, $activePage, $pages) {
59 // first page
60 if ($activePage != $pageNo) {
61 return '<li><a href="'.self::insertPageNumber($link, $pageNo).'" title="'.WCF::getLanguage()->getDynamicVariable('wcf.page.pageNo', ['pageNo' => $pageNo]).'">'.StringUtil::formatInteger($pageNo).'</a></li>'."\n";
62 }
63 else {
64 return '<li class="active"><span>'.StringUtil::formatInteger($pageNo).'</span><span class="invisible">'.WCF::getLanguage()->getDynamicVariable('wcf.page.pagePosition', ['pageNo' => $pageNo, 'pages' => $pages]).'</span></li>'."\n";
65 }
66 }
67
68 /**
69 * Generates HTML code for 'previous' link.
70 *
71 * @param string $link
72 * @param integer $pageNo
73 * @return string
74 */
75 protected function makePreviousLink($link, $pageNo) {
76 if ($pageNo > 1) {
77 return '<li class="skip"><a href="'.self::insertPageNumber($link, $pageNo - 1).'" title="'.WCF::getLanguage()->getDynamicVariable('wcf.global.page.previous').'" class="icon icon24 fa-chevron-left jsTooltip"></a></li>'."\n";
78 }
79 else {
80 return '<li class="skip disabled"><span class="icon icon24 fa-chevron-left"></span></li>'."\n";
81 }
82 }
83
84 /**
85 * Generates HTML code for 'next' link.
86 *
87 * @param string $link
88 * @param integer $pageNo
89 * @param integer $pages
90 * @return string
91 */
92 protected function makeNextLink($link, $pageNo, $pages) {
93 if ($pageNo && $pageNo < $pages) {
94 return '<li class="skip"><a href="'.self::insertPageNumber($link, $pageNo + 1).'" title="'.WCF::getLanguage()->getDynamicVariable('wcf.global.page.next').'" class="icon icon24 fa-chevron-right jsTooltip"></a></li>'."\n";
95 }
96 else {
97 return '<li class="skip disabled"><span class="icon icon24 fa-chevron-right"></span></li>'."\n";
98 }
99 }
100
101 /**
102 * @inheritDoc
103 */
104 public function execute($tagArgs, TemplateEngine $tplObj) {
105 // needed params: controller, link, page, pages
106 if (!isset($tagArgs['link'])) throw new SystemException("missing 'link' argument in pages tag");
107 if (!isset($tagArgs['controller'])) throw new SystemException("missing 'controller' argument in pages tag");
108 if (!isset($tagArgs['pages'])) {
109 if (($tagArgs['pages'] = $tplObj->get('pages')) === null) {
110 throw new SystemException("missing 'pages' argument in pages tag");
111 }
112 }
113
114 $html = '';
115
116 if ($tagArgs['pages'] > 1) {
117 // create and encode route link
118 $parameters = [];
119 if (isset($tagArgs['id'])) $parameters['id'] = $tagArgs['id'];
120 if (isset($tagArgs['title'])) $parameters['title'] = $tagArgs['title'];
121 if (isset($tagArgs['object'])) $parameters['object'] = $tagArgs['object'];
122 if (isset($tagArgs['application'])) $parameters['application'] = $tagArgs['application'];
123
124 $link = StringUtil::encodeHTML(LinkHandler::getInstance()->getLink($tagArgs['controller'], $parameters, $tagArgs['link']));
125
126 if (!isset($tagArgs['page'])) {
127 if (($tagArgs['page'] = $tplObj->get('pageNo')) === null) {
128 $tagArgs['page'] = 0;
129 }
130 }
131
132 // open div and ul
133 $html .= "<nav class=\"".$this->cssClassName."\" data-link=\"".$link."\" data-pages=\"".$tagArgs['pages']."\">\n<ul>\n";
134
135 // previous page
136 $html .= $this->makePreviousLink($link, $tagArgs['page']);
137
138 // first page
139 $html .= $this->makeLink($link, 1, $tagArgs['page'], $tagArgs['pages']);
140
141 // calculate page links
142 $maxLinks = static::SHOW_LINKS - 4;
143 $linksBeforePage = $tagArgs['page'] - 2;
144 if ($linksBeforePage < 0) $linksBeforePage = 0;
145 $linksAfterPage = $tagArgs['pages'] - ($tagArgs['page'] + 1);
146 if ($linksAfterPage < 0) $linksAfterPage = 0;
147 if ($tagArgs['page'] > 1 && $tagArgs['page'] < $tagArgs['pages']) {
148 $maxLinks--;
149 }
150
151 $half = $maxLinks / 2;
152 $left = $right = $tagArgs['page'];
153 if ($left < 1) $left = 1;
154 if ($right < 1) $right = 1;
155 if ($right > $tagArgs['pages'] - 1) $right = $tagArgs['pages'] - 1;
156
157 if ($linksBeforePage >= $half) {
158 $left -= $half;
159 }
160 else {
161 $left -= $linksBeforePage;
162 $right += $half - $linksBeforePage;
163 }
164
165 if ($linksAfterPage >= $half) {
166 $right += $half;
167 }
168 else {
169 $right += $linksAfterPage;
170 $left -= $half - $linksAfterPage;
171 }
172
173 $right = intval(ceil($right));
174 $left = intval(ceil($left));
175 if ($left < 1) $left = 1;
176 if ($right > $tagArgs['pages']) $right = $tagArgs['pages'];
177
178 // left ... links
179 if ($left > 1) {
180 if ($left - 1 < 2) {
181 $html .= $this->makeLink($link, 2, $tagArgs['page'], $tagArgs['pages']);
182 }
183 else {
184 $html .= '<li class="jumpTo"><a title="'.WCF::getLanguage()->getDynamicVariable('wcf.page.jumpTo').'" class="jsTooltip">'.StringUtil::HELLIP.'</a></li>'."\n";
185 }
186 }
187
188 // visible links
189 for ($i = $left + 1; $i < $right; $i++) {
190 $html .= $this->makeLink($link, $i, $tagArgs['page'], $tagArgs['pages']);
191 }
192
193 // right ... links
194 if ($right < $tagArgs['pages']) {
195 if ($tagArgs['pages'] - $right < 2) {
196 $html .= $this->makeLink($link, $tagArgs['pages'] - 1, $tagArgs['page'], $tagArgs['pages']);
197 }
198 else {
199 $html .= '<li class="jumpTo"><a title="'.WCF::getLanguage()->getDynamicVariable('wcf.page.jumpTo').'" class="jsTooltip">'.StringUtil::HELLIP.'</a></li>'."\n";
200 }
201 }
202
203 // last page
204 $html .= $this->makeLink($link, $tagArgs['pages'], $tagArgs['page'], $tagArgs['pages']);
205
206 // next page
207 $html .= $this->makeNextLink($link, $tagArgs['page'], $tagArgs['pages']);
208
209 // close div and ul
210 $html .= "</ul></nav>\n";
211 }
212
213 // assign html output to template var
214 if (isset($tagArgs['assign'])) {
215 $tplObj->assign($tagArgs['assign'], $html);
216 if (!isset($tagArgs['print']) || !$tagArgs['print']) return '';
217 }
218
219 return $html;
220 }
221 }