Browse code

Sanitize the filtering to only show applicable slots representing the set filters

Benjamin Roth authored on21/08/2025 16:45:11
Showing1 changed files
... ...
@@ -69,9 +69,11 @@ class WeinanlieferungSlotsListModuleController extends AbstractFrontendModuleCon
69 69
 
70 70
             // Support unit-prefixed values like "u1-16" (unit-specific) and legacy "u-16". Both resolve to numeric capacity 16 for SQL.
71 71
             $filterNumeric = null;
72
-            if (preg_match('/^u\d+-(\d+)$/', $filterRaw, $m)) {
72
+            $filterUnitId = null;
73
+            if (preg_match('/^u(\d+)-(\d+)$/', $filterRaw, $m)) {
73 74
                 // New format: u<unitId>-<capacity>
74
-                $filterNumeric = (int) $m[1];
75
+                $filterUnitId = (int) $m[1];
76
+                $filterNumeric = (int) $m[2];
75 77
             } elseif (preg_match('/^u-(\d+)$/', $filterRaw, $m)) {
76 78
                 // Legacy format kept for backward compatibility: u-<capacity>
77 79
                 $filterNumeric = (int) $m[1];
... ...
@@ -79,8 +81,16 @@ class WeinanlieferungSlotsListModuleController extends AbstractFrontendModuleCon
79 81
                 $filterNumeric = (int) $filterRaw;
80 82
             }
81 83
 
84
+            // Capacity availability condition
82 85
             $arrOptions['column'][] = '(SELECT tl_vr_wa_slot.behaelter - IFNULL(SUM(tl_vr_wa_reservation.behaelter),0) FROM tl_vr_wa_reservation WHERE tl_vr_wa_reservation.pid = tl_vr_wa_slot.id) >= ?';
83 86
             $arrOptions['value'][] = $filterNumeric;
87
+
88
+            // If a specific unit was selected (new format), restrict slots to Standorte that have this unit enabled
89
+            if ($filterUnitId !== null) {
90
+                // units is a serialized array, match serialized occurrence of the unit id
91
+                $arrOptions['column'][] = 'pid IN (SELECT id FROM tl_vr_wa_standort WHERE units REGEXP ?)';
92
+                $arrOptions['value'][] = 's:[0-9]+:"' . $filterUnitId . '"';
93
+            }
84 94
         }
85 95
         if (!empty($_GET['filter_standort']))
86 96
         {
... ...
@@ -209,10 +219,49 @@ class WeinanlieferungSlotsListModuleController extends AbstractFrontendModuleCon
209 219
                 }
210 220
             }
211 221
 
212
-            // Append unit options at the bottom, without exceeding max capacity and only for allowed units
222
+            // Build a map of units enabled per shown Standort and compute per-unit max available capacity across shown slots
223
+            $unitsPerStandort = [];
224
+            $unitMaxAvailable = [];
225
+            if (!empty($shownStandortIds)) {
226
+                if (($ShownStandorte = WeinanlieferungStandortModel::findBy(["id IN (" . implode(',', $shownStandortIds) . ")"], null)) !== null) {
227
+                    foreach ($ShownStandorte as $ShownStandort) {
228
+                        $sid = (int) $ShownStandort->id;
229
+                        $ids = \Contao\StringUtil::deserialize($ShownStandort->units, true);
230
+                        if (!empty($ids)) {
231
+                            foreach ($ids as $uid) {
232
+                                $uid = (int) $uid;
233
+                                $unitsPerStandort[$sid][$uid] = true;
234
+                                // initialize unit max availability bucket
235
+                                if (!isset($unitMaxAvailable[$uid])) {
236
+                                    $unitMaxAvailable[$uid] = 0;
237
+                                }
238
+                            }
239
+                        }
240
+                    }
241
+                }
242
+            }
243
+
244
+            // Iterate the shown slots and, for each, update max available for the units enabled at that slot's Standort
245
+            if (!empty($unitsPerStandort) && !empty($slotIds)) {
246
+                foreach ($slots as $slot) {
247
+                    $sid = (int) $slot->pid;
248
+                    if (empty($unitsPerStandort[$sid])) {
249
+                        continue;
250
+                    }
251
+                    $available = max(0, (int) $slot->getAvailableBehaelter());
252
+                    foreach ($unitsPerStandort[$sid] as $uid => $_true) {
253
+                        if ($available > ($unitMaxAvailable[$uid] ?? 0)) {
254
+                            $unitMaxAvailable[$uid] = $available;
255
+                        }
256
+                    }
257
+                }
258
+            }
259
+
260
+            // Append unit options at the bottom, without exceeding per-unit max availability and only for allowed units
213 261
             if (!empty($allowedUnitIds) && ($Units = WeinanlieferungUnitsModel::findAll()) !== null) {
214 262
                 foreach ($Units as $unit) {
215
-                    if (empty($allowedUnitIds[(int)$unit->id])) {
263
+                    $unitId = (int) $unit->id;
264
+                    if (empty($allowedUnitIds[$unitId])) {
216 265
                         continue; // this unit is not enabled on any shown standort
217 266
                     }
218 267
 
... ...
@@ -222,14 +271,18 @@ class WeinanlieferungSlotsListModuleController extends AbstractFrontendModuleCon
222 271
                     }
223 272
 
224 273
                     $unitName = $unit->description ?: $unit->title; // visible unit name
225
-                    $multiplierMax = intdiv($max, $unitContainers);
274
+                    $unitCap = (int) ($unitMaxAvailable[$unitId] ?? 0);
275
+                    $multiplierMax = intdiv($unitCap, $unitContainers);
276
+                    if ($multiplierMax <= 0) {
277
+                        continue; // nothing available for this unit across shown slots
278
+                    }
226 279
 
227 280
                     for ($m = 1; $m <= $multiplierMax; $m++) {
228 281
                         $value = (string) ($m * $unitContainers);
229 282
                         $label = $m . ' ' . $unitName;
230 283
 
231 284
                         $options[] = [
232
-                            'value' => 'u' . $unit->id . '-' . $value,
285
+                            'value' => 'u' . $unitId . '-' . $value,
233 286
                             'label' => $label,
234 287
                         ];
235 288
                     }