PluginProbe ʕ •ᴥ•ʔ
FAPI Member / 2.2.24
FAPI Member v2.2.24
2.2.33 2.2.32 trunk 1.9.47 2.1.18 2.2.24 2.2.25 2.2.26 2.2.28 2.2.29 2.2.30 2.2.31
fapi-member / src / Service / LevelOrderService.php
fapi-member / src / Service Last commit date
ApiService.php 11 months ago ElementService.php 11 months ago EmailService.php 11 months ago FormService.php 11 months ago LevelOrderService.php 11 months ago LevelService.php 11 months ago MembershipService.php 11 months ago RedirectService.php 11 months ago SanitizationService.php 11 months ago StatisticsService.php 11 months ago UserService.php 11 months ago
LevelOrderService.php
212 lines
1 <?php declare(strict_types=1);
2
3 namespace FapiMember\Service;
4
5 use FapiMember\Container\Container;
6 use FapiMember\Model\MemberSection;
7 use FapiMember\Repository\LevelOrderRepository;
8 use FapiMember\Repository\LevelRepository;
9
10 class LevelOrderService
11 {
12 private LevelRepository $levelRepository;
13 private LevelOrderRepository $levelOrderRepository;
14
15 public function __construct()
16 {
17 $this->levelRepository = Container::get(LevelRepository::class);
18 $this->levelOrderRepository = Container::get(LevelOrderRepository::class);
19 }
20
21 public function reorder(int $reorderedLevelId, int $direction): bool
22 {
23 if ($direction !== 1 && $direction !== -1) {
24 return false;
25 }
26
27 $ordering = $this->getOrder();
28 $reorderedSectionIndex = null;
29 $reorderedLevelIndex = null;
30 $reordered = false;
31
32 if (isset($ordering[$reorderedLevelId])) {
33 $reorderedSectionIndex = $ordering[$reorderedLevelId]['index'];
34 }
35
36 foreach ($ordering as $orderSectionId => $orderSection) {
37 if ($reorderedSectionIndex !== null) {
38 if ($orderSection['index'] === $reorderedSectionIndex + $direction) {
39 $ordering[$reorderedLevelId]['index'] = $orderSection['index'];
40 $ordering[$orderSectionId]['index'] = $reorderedSectionIndex;
41 $reordered = true;
42 }
43 } else {
44 $orderLevels = $orderSection['levels'];
45 if (isset($orderLevels[$reorderedLevelId])) {
46 $reorderedLevelIndex = $orderLevels[$reorderedLevelId];
47 }
48
49 if ($reorderedLevelIndex !== null) {
50 foreach ($orderLevels as $orderLevelId => $orderLevel) {
51 if ($orderLevel === $reorderedLevelIndex + $direction) {
52 $ordering[$orderSectionId]['levels'][$reorderedLevelId] = $orderLevel;
53 $ordering[$orderSectionId]['levels'][$orderLevelId] = $reorderedLevelIndex;
54 $reordered = true;
55 }
56 }
57
58 break;
59 }
60 }
61 }
62
63 $this->levelOrderRepository->set($ordering);
64
65 return $reordered;
66 }
67
68 public function getOrder(): array
69 {
70 $this->initializeOrder();
71 return $this->levelOrderRepository->get();
72 }
73
74 public function initializeOrder(): void
75 {
76 $sections = $this->levelRepository->getAllSections();
77 $ordering = $this->levelOrderRepository->get();
78
79 if (empty($ordering)) {
80 $ordering = $this->createOrder($sections);
81 } else {
82 $ordering = $this->fixOrder($ordering, $sections);
83 }
84
85 $this->levelOrderRepository->set($ordering);
86 }
87
88 /** @param array<MemberSection> $sections */
89 private function createOrder(array $sections): array
90 {
91 $ordering = [];
92
93 foreach ($sections as $sectionIndex => $section) {
94 $ordering[$section->getId()] = [
95 'index' => $sectionIndex,
96 'levels' => [],
97 ];
98
99 $levels = $section->getLevels();
100
101 foreach ($levels as $levelIndex => $level) {
102 $ordering[$section->getId()]['levels'][$level->getId()] = $levelIndex;
103 }
104 }
105
106 return $ordering;
107 }
108
109 /** @param array<MemberSection> $sections */
110 private function fixOrder(array $ordering, array $sections): array
111 {
112 $ordering = $this->removeNonExistentOrderItems($ordering, $sections);
113 $ordering = $this->shiftOrderIndexes($ordering);
114 $ordering = $this->addMissingOrderItems($ordering, $sections);
115
116 return $ordering;
117 }
118
119 /** @param array<MemberSection> $sections */
120 private function removeNonExistentOrderItems(array $ordering, array $sections): array
121 {
122 $newOrdering = [];
123
124 foreach ($sections as $section) {
125 $levelsOrder = [];
126
127 foreach ($section->getLevels() as $level) {
128 if (isset(
129 $ordering[$section->getId()]['levels'][$level->getId()]
130 )) {
131 $levelsOrder[$level->getId()] = $ordering[$section->getId()]['levels'][$level->getId()];
132 }
133 }
134
135 if (isset($ordering[$section->getId()])) {
136 $newOrdering[$section->getId()] = ['levels' => $levelsOrder, 'index' => $ordering[$section->getId()]['index']];
137 }
138 }
139
140 return $newOrdering;
141 }
142
143 private function shiftOrderIndexes(array $ordering): array
144 {
145 $sectionIndexes = array_column($ordering, 'index');
146 sort($sectionIndexes);
147
148 $sectionIndexMap = array_flip($sectionIndexes);
149 $newOrdering = [];
150
151 foreach ($ordering as $sectionId => $sectionData) {
152 $newSectionIndex = $sectionIndexMap[$sectionData['index']];
153
154 $levelIndexes = array_values($sectionData['levels']);
155 sort($levelIndexes);
156
157 $levelIndexMap = array_flip($levelIndexes);
158 $newLevels = [];
159 foreach ($sectionData['levels'] as $levelId => $levelIndex) {
160 $newLevels[$levelId] = $levelIndexMap[$levelIndex];
161 }
162
163 $newOrdering[$sectionId] = [
164 'index' => $newSectionIndex,
165 'levels' => $newLevels,
166 ];
167 }
168
169 return $newOrdering;
170 }
171
172 /** @param array<MemberSection> $sections */
173 private function addMissingOrderItems(array $ordering, array $sections): array
174 {
175 $existingSectionIds = array_keys($ordering);
176 $existingLevelIds = [];
177 $nextSectionIndex = count($ordering);
178 $nextLevelIndexes = [];
179
180 foreach ($ordering as $sectionId => $sectionData) {
181 $existingLevelIds = array_merge($existingLevelIds, array_keys($sectionData['levels']));
182 $nextLevelIndexes[$sectionId] = count($sectionData['levels']);
183 }
184
185
186 foreach ($sections as $section) {
187 $sectionId = $section->getId();
188 if (!in_array($sectionId, $existingSectionIds, true)) {
189 // New section
190 $ordering[$sectionId] = [
191 'index' => $nextSectionIndex++,
192 'levels' => [],
193 ];
194 $nextLevelIndexes[$sectionId] = 0;
195 }
196
197 foreach ($section->getLevels() as $level) {
198 $levelId = $level->getId();
199 if (!in_array($levelId, $existingLevelIds, true)) {
200 $ordering[$sectionId]['levels'][$levelId] = $nextLevelIndexes[$sectionId]++;
201 }
202 }
203 }
204
205 return $ordering;
206 }
207
208
209
210
211 }
212