PluginProbe ʕ •ᴥ•ʔ
FAPI Member / trunk
FAPI Member vtrunk
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
AdminMenuService.php 2 years ago ApiService.php 1 day ago ElementService.php 7 months ago EmailService.php 1 day ago FormService.php 1 year ago LevelOrderService.php 1 year ago LevelService.php 1 year ago MembershipService.php 1 year ago RedirectService.php 1 year ago SanitizationService.php 2 years ago StatisticsService.php 1 year ago UserService.php 1 year 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