7ebd24487b66eb932150326854e0bd572ddced6a
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / ContentObject / Menu / CategoryMenuUtility.php
1 <?php
2 namespace TYPO3\CMS\Frontend\ContentObject\Menu;
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
17 use TYPO3\CMS\Core\Collection\AbstractRecordCollection;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19 use TYPO3\CMS\Frontend\Category\Collection\CategoryCollection;
20
21 /**
22 * Utility class for menus based on category collections of pages.
23 *
24 * Returns all the relevant pages for rendering with a menu content object.
25 *
26 * @author Francois Suter <francois.suter@typo3.org>
27 */
28 class CategoryMenuUtility {
29
30 /**
31 * @var string Name of the field used for sorting the pages
32 */
33 static protected $sortingField;
34
35 /**
36 * Collects all pages for the selected categories, sorted according to configuration.
37 *
38 * @param string $selectedCategories Comma-separated list of system categories primary keys
39 * @param array $configuration TypoScript configuration for the "special." keyword
40 * @param \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject $parentObject Back-reference to the calling object
41 * @return string List of selected pages
42 */
43 public function collectPages($selectedCategories, $configuration, $parentObject) {
44 $selectedPages = array();
45 $categoriesPerPage = array();
46 // Determine the name of the relation field
47 $relationField = '';
48 if (isset($configuration['relation.'])) {
49 $relationField = $parentObject->parent_cObj->stdWrap(
50 $configuration['relation'],
51 $configuration['relation.']
52 );
53 } elseif (isset($configuration['relation'])) {
54 $relationField = $configuration['relation'];
55 }
56 // Get the pages for each selected category
57 $selectedCategories = GeneralUtility::intExplode(',', $selectedCategories, TRUE);
58 foreach ($selectedCategories as $aCategory) {
59 $collection = CategoryCollection::load(
60 $aCategory,
61 TRUE,
62 'pages',
63 $relationField
64 );
65 $categoryUid = 0;
66 if ($collection instanceof AbstractRecordCollection) {
67 $categoryUid = $collection->getUid();
68 }
69 // Loop on the results, overlay each page record found
70 foreach ($collection as $pageItem) {
71 $parentObject->getSysPage()->versionOL('pages', $pageItem, TRUE);
72 if (is_array($pageItem)) {
73 $selectedPages[$pageItem['uid']] = $parentObject->getSysPage()->getPageOverlay($pageItem);
74 // Keep a list of the categories each page belongs to
75 if (!isset($categoriesPerPage[$pageItem['uid']])) {
76 $categoriesPerPage[$pageItem['uid']] = array();
77 }
78 $categoriesPerPage[$pageItem['uid']][] = $categoryUid;
79 }
80 }
81 }
82 // Loop on the selected pages to add the categories they belong to, as comma-separated list of category uid's)
83 // (this makes them available for rendering, if needed)
84 foreach ($selectedPages as $uid => $pageRecord) {
85 $selectedPages[$uid]['_categories'] = implode(',', $categoriesPerPage[$uid]);
86 }
87
88 // Sort the pages according to the sorting property
89 self::$sortingField = isset($configuration['sorting.']) ? $parentObject->getParentContentObject()->stdWrap($configuration['sorting'], $configuration['sorting.']) : $configuration['sorting'];
90 $order = isset($configuration['order.']) ? $parentObject->getParentContentObject()->stdWrap($configuration['order'], $configuration['order.']) : $configuration['order'];
91 $selectedPages = $this->sortPages($selectedPages, $order);
92
93 return $selectedPages;
94 }
95
96 /**
97 * Sorts the selected pages
98 *
99 * If the sorting field is not defined or does not corresponding to an existing field
100 * of the "pages" tables, the list of pages will remain unchanged.
101 *
102 * @param array $pages List of selected pages
103 * @param string $order Order for sorting (should "asc" or "desc")
104 * @return array Sorted list of pages
105 */
106 protected function sortPages($pages, $order) {
107 // Perform the sorting only if a criterion was actually defined
108 if (!empty(self::$sortingField)) {
109 // Check that the sorting field exists (checking the first record is enough)
110 $firstPage = current($pages);
111 if (isset($firstPage[self::$sortingField])) {
112 // Make sure the order property is either "asc" or "desc" (default is "asc")
113 if (!empty($order)) {
114 $order = strtolower($order);
115 if ($order != 'desc') {
116 $order = 'asc';
117 }
118 }
119 uasort(
120 $pages,
121 array(
122 CategoryMenuUtility::class,
123 'sortPagesUtility'
124 )
125 );
126 // If the sort order is descending, reverse the sorted array
127 if ($order == 'desc') {
128 $pages = array_reverse($pages, TRUE);
129 }
130 }
131 }
132 return $pages;
133 }
134
135 /**
136 * Static utility for sorting pages according to the selected criterion
137 *
138 * @param array $pageA Record for first page to be compared
139 * @param array $pageB Record for second page to be compared
140 * @return array -1 if first argument is smaller than second argument, 1 if first is greater than second and 0 if both are equal
141 */
142 static public function sortPagesUtility($pageA, $pageB) {
143 return strnatcasecmp($pageA[self::$sortingField], $pageB[self::$sortingField]);
144 }
145
146 }