Completed
Push — master ( 8e078a...edce3c )
by
unknown
15:28
created

CategoryMenuUtility::collectPages()   B

Complexity

Conditions 7
Paths 18

Size

Total Lines 44
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 26
nc 18
nop 3
dl 0
loc 44
rs 8.5706
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Frontend\ContentObject\Menu;
17
18
use TYPO3\CMS\Core\Collection\AbstractRecordCollection;
19
use TYPO3\CMS\Core\Utility\GeneralUtility;
20
use TYPO3\CMS\Frontend\Category\Collection\CategoryCollection;
21
22
/**
23
 * Utility class for menus based on category collections of pages.
24
 *
25
 * Returns all the relevant pages for rendering with a menu content object.
26
 * @internal this is only used for internal purposes and solely used for EXT:frontend and not part of TYPO3's Core API.
27
 */
28
class CategoryMenuUtility
29
{
30
    /**
31
     * @var string Name of the field used for sorting the pages
32
     */
33
    protected static $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 array List of selected pages
42
     */
43
    public function collectPages($selectedCategories, $configuration, $parentObject)
44
    {
45
        $selectedPages = [];
46
        $categoriesPerPage = [];
47
        // Determine the name of the relation field
48
        $relationField = $parentObject->getParentContentObject()->stdWrapValue('relation', $configuration);
49
        // Get the pages for each selected category
50
        $selectedCategories = GeneralUtility::intExplode(',', $selectedCategories, true);
51
        foreach ($selectedCategories as $aCategory) {
52
            $collection = CategoryCollection::load(
53
                $aCategory,
54
                true,
55
                'pages',
56
                $relationField
57
            );
58
            $categoryUid = 0;
59
            if ($collection instanceof AbstractRecordCollection) {
60
                $categoryUid = $collection->getUid();
61
            }
62
            // Loop on the results, overlay each page record found
63
            foreach ($collection as $pageItem) {
64
                $parentObject->getSysPage()->versionOL('pages', $pageItem, true);
65
                if (is_array($pageItem)) {
66
                    $selectedPages[$pageItem['uid']] = $parentObject->getSysPage()->getPageOverlay($pageItem);
67
                    // Keep a list of the categories each page belongs to
68
                    if (!isset($categoriesPerPage[$pageItem['uid']])) {
69
                        $categoriesPerPage[$pageItem['uid']] = [];
70
                    }
71
                    $categoriesPerPage[$pageItem['uid']][] = $categoryUid;
72
                }
73
            }
74
        }
75
        // Loop on the selected pages to add the categories they belong to, as comma-separated list of category uid's)
76
        // (this makes them available for rendering, if needed)
77
        foreach ($selectedPages as $uid => $pageRecord) {
78
            $selectedPages[$uid]['_categories'] = implode(',', $categoriesPerPage[$uid]);
79
        }
80
81
        // Sort the pages according to the sorting property
82
        self::$sortingField = $parentObject->getParentContentObject()->stdWrapValue('sorting', $configuration);
83
        $order = $parentObject->getParentContentObject()->stdWrapValue('order', $configuration);
84
        $selectedPages = $this->sortPages($selectedPages, $order);
85
86
        return $selectedPages;
87
    }
88
89
    /**
90
     * Sorts the selected pages
91
     *
92
     * If the sorting field is not defined or does not corresponding to an existing field
93
     * of the "pages" tables, the list of pages will remain unchanged.
94
     *
95
     * @param array $pages List of selected pages
96
     * @param string $order Order for sorting (should "asc" or "desc")
97
     * @return array Sorted list of pages
98
     */
99
    protected function sortPages($pages, $order)
100
    {
101
        // Perform the sorting only if a criterion was actually defined
102
        if (!empty(self::$sortingField)) {
103
            // Check that the sorting field exists (checking the first record is enough)
104
            $firstPage = current($pages);
105
            if (isset($firstPage[self::$sortingField])) {
106
                // Make sure the order property is either "asc" or "desc" (default is "asc")
107
                if (!empty($order)) {
108
                    $order = strtolower($order);
109
                    if ($order !== 'desc') {
110
                        $order = 'asc';
111
                    }
112
                }
113
                uasort(
114
                    $pages,
115
                    [
116
                        self::class,
117
                        'sortPagesUtility'
118
                    ]
119
                );
120
                // If the sort order is descending, reverse the sorted array
121
                if ($order === 'desc') {
122
                    $pages = array_reverse($pages, true);
123
                }
124
            }
125
        }
126
        return $pages;
127
    }
128
129
    /**
130
     * Static utility for sorting pages according to the selected criterion
131
     *
132
     * @param array $pageA Record for first page to be compared
133
     * @param array $pageB Record for second page to be compared
134
     * @return array -1 if first argument is smaller than second argument, 1 if first is greater than second and 0 if both are equal
135
     */
136
    public static function sortPagesUtility($pageA, $pageB)
137
    {
138
        return strnatcasecmp($pageA[self::$sortingField], $pageB[self::$sortingField]);
0 ignored issues
show
Bug Best Practice introduced by
The expression return strnatcasecmp($pa...eB[self::sortingField]) returns the type integer which is incompatible with the documented return type array.
Loading history...
139
    }
140
}
141