Add unit tests for department lane dynamic image overrides and introduce classes for self-serve signal and virtual hardware management

- Add `DepartmentLaneDynamicImageRouteTest` to verify dynamic image preview handling for studio lanes.
- Introduce `selfserve_machine_signal` class to standardize signal normalization, recording, and gateway signal management workflows.
- Add `selfserve_virtual_hardware` class to handle virtual hardware configurations, including gateway and binding management.
- Enhance structure with auxiliary methods for payload normalization, workspace merging, and validation warnings.
This commit is contained in:
Jeppe Bundgaard
2026-04-29 09:52:51 +02:00
parent 690e114d38
commit eeccacb2a7
33 changed files with 4880 additions and 140 deletions
@@ -33,7 +33,7 @@ class department_selfserve_tasks_o extends db
public object_property $description; // The task description
public object_property $order_priority; // The order priority of the task (lower numbers are shown first)
public object_property $services; // The services that the task enables (json), this is used to enable machine wash.
public object_property $buttons; // The buttons on the departments machine dynamic image that should be enabled by this task (json array of button ids)
public object_property $buttons; // The buttons on the departments machine dynamic image that should be enabled by this task (json array of mapped button ids)
public object_property $dynamic_images_vehicle_type; // The vehicle type selection override on the machine, used by dynamicimages - int or null if not applicable.
public object_property $created_at;
public object_property $updated_at;
@@ -72,7 +72,7 @@ class department_selfserve_tasks_o extends db
* @param string $description The task description
* @param int $order_priority The order priority of the task (lower numbers are shown first)
* @param selfserve_lane_services[]|string[]|null $services The services that the task enables (stored as JSON array of service names). May be an array of enum cases or names.
* @param array<int>|string|null $buttons Optional buttons on the department's machine dynamic image to be enabled by this task (stored as JSON array of button IDs). Accepts array of ints or a parsable string/JSON.
* @param array<int|string>|string|null $buttons Optional buttons on the department's machine dynamic image to be enabled by this task (stored as JSON array of button IDs). Accepts program integers plus "reset" and "start".
* @param int|null $dynamic_images_vehicle_type Optional vehicle type selection override for the machine UI. Integer >= 0 or null.
* @return department_selfserve_tasks_o
* @throws Exception If the object was not created successfully
@@ -358,13 +358,13 @@ class department_selfserve_tasks_o extends db
return $val;
}
/**
* Normalize mixed input for buttons into an array of integer IDs (>= 0).
* Normalize mixed input for buttons into an array of mapped button IDs.
* Accepts:
* - array of ints/strings
* - JSON array string
* - comma-separated string
* @param mixed $input
* @return array<int>
* @return array<int|string>
* @throws Exception
*/
public static function normalizeButtonsInput(mixed $input): array
@@ -379,14 +379,22 @@ class department_selfserve_tasks_o extends db
}
}
if (!is_array($raw)) {
throw new Exception('Invalid format for buttons. Expected array, JSON array, or comma-separated string of integers.');
throw new Exception('Invalid format for buttons. Expected array, JSON array, or comma-separated string of mapped button ids.');
}
$ids = [];
foreach ($raw as $btn) {
if (is_string($btn)) {
$trimmed = trim($btn);
$specialButton = strtolower($trimmed);
if ($specialButton === 'reset' || $specialButton === 'start') {
$ids[] = $specialButton;
continue;
}
}
if (is_int($btn)) {
$val = $btn;
} elseif (is_string($btn) && ctype_digit($btn)) {
$val = (int)$btn;
} elseif (is_string($btn) && ctype_digit(trim($btn))) {
$val = (int)trim($btn);
} elseif (is_numeric($btn) && (int)$btn == $btn) {
$val = (int)$btn;
} else {
@@ -398,7 +406,16 @@ class department_selfserve_tasks_o extends db
$ids[] = $val;
}
// de-duplicate while preserving order
$ids = array_values(array_unique($ids));
return $ids;
$deduped = [];
$seen = [];
foreach ($ids as $id) {
$key = (is_int($id) ? 'int:' : 'string:') . (string)$id;
if (isset($seen[$key])) {
continue;
}
$seen[$key] = true;
$deduped[] = $id;
}
return $deduped;
}
}
@@ -63,7 +63,7 @@ class selfserve_wash_session_tasks_o extends db
'description' => $description,
'services' => $services,
'buttons' => $buttons,
'dynamic_images_vehicle_type' => (int)$thumb_position, // The rotations to do on the image.
'dynamic_images_vehicle_type' => $thumb_position === null ? null : (int)$thumb_position, // The rotations to do on the image.
]);
$this->getObjectProperties();
$this->objectChanged();