[TASK] Update php-cs-fixer to 2.5.0
[Packages/TYPO3.CMS.git] / typo3 / sysext / fluid / Classes / ViewHelpers / Widget / Controller / PaginateController.php
1 <?php
2 namespace TYPO3\CMS\Fluid\ViewHelpers\Widget\Controller;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16 use TYPO3\CMS\Core\Utility\ArrayUtility;
17 use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
18 use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
19 use TYPO3\CMS\Fluid\Core\Widget\AbstractWidgetController;
20
21 /**
22 * Class PaginateController
23 */
24 class PaginateController extends AbstractWidgetController
25 {
26 /**
27 * @var array
28 */
29 protected $configuration = [
30 'itemsPerPage' => 10,
31 'insertAbove' => false,
32 'insertBelow' => true,
33 'maximumNumberOfLinks' => 99,
34 'addQueryStringMethod' => '',
35 'section' => ''
36 ];
37
38 /**
39 * @var QueryResultInterface|ObjectStorage|array
40 */
41 protected $objects;
42
43 /**
44 * @var int
45 */
46 protected $currentPage = 1;
47
48 /**
49 * @var int
50 */
51 protected $maximumNumberOfLinks = 99;
52
53 /**
54 * @var int
55 */
56 protected $numberOfPages = 1;
57
58 /**
59 * @var int
60 */
61 protected $displayRangeStart = null;
62
63 /**
64 * @var int
65 */
66 protected $displayRangeEnd = null;
67
68 /**
69 * Initializes the current information on which page the visitor is.
70 */
71 public function initializeAction()
72 {
73 $this->objects = $this->widgetConfiguration['objects'];
74 ArrayUtility::mergeRecursiveWithOverrule($this->configuration, $this->widgetConfiguration['configuration'], false);
75 $itemsPerPage = (int)$this->configuration['itemsPerPage'];
76 $this->numberOfPages = $itemsPerPage > 0 ? ceil(count($this->objects) / $itemsPerPage) : 0;
77 $this->maximumNumberOfLinks = (int)$this->configuration['maximumNumberOfLinks'];
78 }
79
80 /**
81 * @param int $currentPage
82 */
83 public function indexAction($currentPage = 1)
84 {
85 // set current page
86 $this->currentPage = (int)$currentPage;
87 if ($this->currentPage < 1) {
88 $this->currentPage = 1;
89 }
90 if ($this->currentPage > $this->numberOfPages) {
91 // set $modifiedObjects to NULL if the page does not exist
92 $modifiedObjects = null;
93 } else {
94 // modify query
95 $itemsPerPage = (int)$this->configuration['itemsPerPage'];
96 $offset = 0;
97 if ($this->currentPage > 1) {
98 $offset = ((int)($itemsPerPage * ($this->currentPage - 1)));
99 }
100 $modifiedObjects = $this->prepareObjectsSlice($itemsPerPage, $offset);
101 }
102 $this->view->assign('contentArguments', [
103 $this->widgetConfiguration['as'] => $modifiedObjects
104 ]);
105 $this->view->assign('configuration', $this->configuration);
106 $this->view->assign('pagination', $this->buildPagination());
107 }
108
109 /**
110 * If a certain number of links should be displayed, adjust before and after
111 * amounts accordingly.
112 */
113 protected function calculateDisplayRange()
114 {
115 $maximumNumberOfLinks = $this->maximumNumberOfLinks;
116 if ($maximumNumberOfLinks > $this->numberOfPages) {
117 $maximumNumberOfLinks = $this->numberOfPages;
118 }
119 $delta = floor($maximumNumberOfLinks / 2);
120 $this->displayRangeStart = $this->currentPage - $delta;
121 $this->displayRangeEnd = $this->currentPage + $delta - ($maximumNumberOfLinks % 2 === 0 ? 1 : 0);
122 if ($this->displayRangeStart < 1) {
123 $this->displayRangeEnd -= $this->displayRangeStart - 1;
124 }
125 if ($this->displayRangeEnd > $this->numberOfPages) {
126 $this->displayRangeStart -= $this->displayRangeEnd - $this->numberOfPages;
127 }
128 $this->displayRangeStart = (int)max($this->displayRangeStart, 1);
129 $this->displayRangeEnd = (int)min($this->displayRangeEnd, $this->numberOfPages);
130 }
131
132 /**
133 * Returns an array with the keys "pages", "current", "numberOfPages",
134 * "nextPage" & "previousPage"
135 *
136 * @return array
137 */
138 protected function buildPagination()
139 {
140 $this->calculateDisplayRange();
141 $pages = [];
142 for ($i = $this->displayRangeStart; $i <= $this->displayRangeEnd; $i++) {
143 $pages[] = ['number' => $i, 'isCurrent' => $i === $this->currentPage];
144 }
145 $pagination = [
146 'pages' => $pages,
147 'current' => $this->currentPage,
148 'numberOfPages' => $this->numberOfPages,
149 'displayRangeStart' => $this->displayRangeStart,
150 'displayRangeEnd' => $this->displayRangeEnd,
151 'hasLessPages' => $this->displayRangeStart > 2,
152 'hasMorePages' => $this->displayRangeEnd + 1 < $this->numberOfPages
153 ];
154 if ($this->currentPage < $this->numberOfPages) {
155 $pagination['nextPage'] = $this->currentPage + 1;
156 }
157 if ($this->currentPage > 1) {
158 $pagination['previousPage'] = $this->currentPage - 1;
159 }
160 return $pagination;
161 }
162
163 /**
164 * @param int $itemsPerPage
165 * @param int $offset
166 *
167 * @return array|QueryResultInterface
168 * @throws \InvalidArgumentException
169 */
170 protected function prepareObjectsSlice($itemsPerPage, $offset)
171 {
172 if ($this->objects instanceof QueryResultInterface) {
173 $query = $this->objects->getQuery();
174 $query->setLimit($itemsPerPage);
175 if ($offset > 0) {
176 $query->setOffset($offset);
177 }
178 $modifiedObjects = $query->execute();
179 return $modifiedObjects;
180 }
181 if ($this->objects instanceof ObjectStorage) {
182 $modifiedObjects = [];
183 $objectArray = $this->objects->toArray();
184 $endOfRange = min($offset + $itemsPerPage, count($objectArray));
185 for ($i = $offset; $i < $endOfRange; $i++) {
186 $modifiedObjects[] = $objectArray[$i];
187 }
188 return $modifiedObjects;
189 }
190 if (is_array($this->objects)) {
191 $modifiedObjects = array_slice($this->objects, $offset, $itemsPerPage);
192 return $modifiedObjects;
193 }
194 throw new \InvalidArgumentException(
195 'The view helper "' . get_class($this)
196 . '" accepts as argument "QueryResultInterface", "\SplObjectStorage", "ObjectStorage" or an array. '
197 . 'given: ' . get_class($this->objects),
198 1385547291
199 );
200 }
201 }