Add support for dynamic image buttons and vehicle type selection in self-serve tasks
- Extend `department_selfserve_tasks_o` with `buttons` and `dynamic_images_vehicle_type` properties. - Add normalization/validation methods for `buttons` and `dynamic_images_vehicle_type` parameters. - Update `departmentSelfserveTasksRoute` to handle new fields in task creation and update. - Add OpenAPI specifications for `buttons` and `dynamic_images_vehicle_type`. - Include comprehensive tests for button normalization and vehicle type selection.
This commit is contained in:
@@ -2761,6 +2761,16 @@ paths:
|
||||
description: Optional services enabled by this task. Items must be valid service enum names.
|
||||
items:
|
||||
$ref: '#/components/schemas/SelfserveLaneService'
|
||||
buttons:
|
||||
type: array
|
||||
description: Optional dynamic image button IDs enabled by this task.
|
||||
items:
|
||||
type: integer
|
||||
default: []
|
||||
dynamic_images_vehicle_type:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: Optional vehicle type selection override for the machine UI. Integer >= 0 or null.
|
||||
responses:
|
||||
'200':
|
||||
description: Successfully added task
|
||||
@@ -2813,6 +2823,16 @@ paths:
|
||||
description: Services enabled by this task. Set to null to clear all services.
|
||||
items:
|
||||
$ref: '#/components/schemas/SelfserveLaneService'
|
||||
buttons:
|
||||
type: array
|
||||
nullable: true
|
||||
description: Button IDs enabled by this task. Set to null to clear all buttons.
|
||||
items:
|
||||
type: integer
|
||||
dynamic_images_vehicle_type:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: Vehicle type selection override. Set to null to clear.
|
||||
responses:
|
||||
'200':
|
||||
description: Successfully updated task
|
||||
@@ -6790,6 +6810,16 @@ components:
|
||||
items:
|
||||
$ref: '#/components/schemas/SelfserveLaneService'
|
||||
default: []
|
||||
buttons:
|
||||
type: array
|
||||
description: Dynamic image button IDs enabled by this task.
|
||||
items:
|
||||
type: integer
|
||||
default: []
|
||||
dynamic_images_vehicle_type:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: Optional vehicle type selection override for the machine UI.
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
@@ -7068,6 +7098,10 @@ components:
|
||||
type: string
|
||||
relay_machine_id:
|
||||
type: string
|
||||
dynamic_image_id:
|
||||
type: integer
|
||||
nullable: true
|
||||
minimum: 1
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
@@ -7091,6 +7125,10 @@ components:
|
||||
type: string
|
||||
relay_machine_id:
|
||||
type: string
|
||||
dynamic_image_id:
|
||||
type: integer
|
||||
nullable: true
|
||||
minimum: 1
|
||||
|
||||
DepartmentLaneUpdate:
|
||||
type: object
|
||||
@@ -7109,6 +7147,10 @@ components:
|
||||
type: string
|
||||
relay_machine_id:
|
||||
type: string
|
||||
dynamic_image_id:
|
||||
type: integer
|
||||
nullable: true
|
||||
minimum: 1
|
||||
|
||||
Product:
|
||||
type: object
|
||||
|
||||
@@ -17,6 +17,7 @@ class department_lanes_o extends db
|
||||
public object_property $relay_in_id; // The Shelly relay for the entrance port (if applicable)
|
||||
public object_property $relay_out_id; // The Shelly relay for the exit port (if applicable)
|
||||
public object_property $relay_machine_id; // The Shelly relay for the machine (if applicable)
|
||||
public object_property $dynamic_image_id; // The dynamic image id for the lane (if applicable)
|
||||
public object_property $created_at;
|
||||
public object_property $updated_at;
|
||||
public object_property $deleted_at;
|
||||
@@ -42,10 +43,11 @@ class department_lanes_o extends db
|
||||
* @param string|null $relay_in_id The Shelly relay for the entrance port (if applicable)
|
||||
* @param string|null $relay_out_id The Shelly relay for the exit port (if applicable)
|
||||
* @param string|null $relay_machine_id The Shelly relay for the machine (if applicable)
|
||||
* @param int|null $dynamic_image_id The dynamic image id for the lane (if applicable)
|
||||
* @return department_lanes_o
|
||||
* @throws Exception If the object was not created successfully
|
||||
*/
|
||||
public function add(int $department, string $name, string $relay_in_id = null, string $relay_out_id = null, string $relay_machine_id = null): department_lanes_o
|
||||
public function add(int $department, string $name, string $relay_in_id = null, string $relay_out_id = null, string $relay_machine_id = null, int $dynamic_image_id = null): department_lanes_o
|
||||
{
|
||||
global /** @var db $db */
|
||||
$db;
|
||||
@@ -61,6 +63,12 @@ class department_lanes_o extends db
|
||||
if (!is_null($relay_machine_id)) {
|
||||
$relay_machine_id = $db->escape_string($relay_machine_id);
|
||||
}
|
||||
if (!is_null($dynamic_image_id)) {
|
||||
$dynamic_image_id = (int)$dynamic_image_id;
|
||||
if ($dynamic_image_id <= 0) {
|
||||
throw new Exception('dynamic_image_id must be a positive integer');
|
||||
}
|
||||
}
|
||||
// Add the object
|
||||
$tmp_id = self::add_object([
|
||||
'department' => $department,
|
||||
@@ -68,6 +76,7 @@ class department_lanes_o extends db
|
||||
...(!is_null($relay_in_id) ? ['relay_in_id' => $relay_in_id] : []), // If the relay_in_id is null, it will be set to null in the database
|
||||
...(!is_null($relay_out_id) ? ['relay_out_id' => $relay_out_id] : []), // If the relay_out_id is null, it will be set to null in the database
|
||||
...(!is_null($relay_machine_id) ? ['relay_machine_id' => $relay_machine_id] : []), // If the relay_machine_id is null, it will be set to null in the database
|
||||
...(!is_null($dynamic_image_id) ? ['dynamic_image_id' => $dynamic_image_id] : []), // If the dynamic_image_id is null, it will be set to null in the database
|
||||
]);
|
||||
$this->id = $tmp_id;
|
||||
self::getObjectProperties();
|
||||
@@ -82,6 +91,7 @@ class department_lanes_o extends db
|
||||
$this->relay_in_id = new object_property($this->table, $this->id, 'relay_in_id', 'string', false);
|
||||
$this->relay_out_id = new object_property($this->table, $this->id, 'relay_out_id', 'string', false);
|
||||
$this->relay_machine_id = new object_property($this->table, $this->id, 'relay_machine_id', 'string', false);
|
||||
$this->dynamic_image_id = new object_property($this->table, $this->id, 'dynamic_image_id', 'int', false);
|
||||
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'timestamp', false);
|
||||
$this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'timestamp', false);
|
||||
$this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'timestamp', false);
|
||||
@@ -101,6 +111,7 @@ class department_lanes_o extends db
|
||||
'relay_in_id' => (string)$this->relay_in_id->value(),
|
||||
'relay_out_id' => (string)$this->relay_out_id->value(),
|
||||
'relay_machine_id' => (string)$this->relay_machine_id->value(),
|
||||
'dynamic_image_id' => (function($v){ return $v === null ? null : (int)$v; })($this->dynamic_image_id->value()),
|
||||
// Status of the lane
|
||||
'status' => (string)$this->getLaneStatus()->name,
|
||||
// Timestamps
|
||||
|
||||
@@ -21,6 +21,8 @@ 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 $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;
|
||||
public object_property $deleted_at;
|
||||
@@ -56,11 +58,13 @@ class department_selfserve_tasks_o extends db
|
||||
* @param string $task The task text
|
||||
* @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[]|null $services The services that the task enables (json), this is used to enable machine wash.
|
||||
* @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 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
|
||||
*/
|
||||
public function add(int $department, int $lane, int $product, int|null $condition_id, string $task, string $description, int $order_priority = 0, ?array $services = null): self
|
||||
public function add(int $department, int $lane, int $product, int|null $condition_id, string $task, string $description, int $order_priority = 0, ?array $services = null, array|string|null $buttons = null, int|null $dynamic_images_vehicle_type = null): self
|
||||
{
|
||||
global /** @var db $db */
|
||||
$db;
|
||||
@@ -101,6 +105,20 @@ class department_selfserve_tasks_o extends db
|
||||
throw new Exception("Invalid service type");
|
||||
}
|
||||
}
|
||||
// Normalize/validate buttons
|
||||
$buttons_ids = null;
|
||||
if (!is_null($buttons)) {
|
||||
$buttons_ids = self::normalizeButtonsInput($buttons);
|
||||
}
|
||||
|
||||
// Normalize/validate dynamic_images_vehicle_type (nullable, integer >= 0)
|
||||
if (!is_null($dynamic_images_vehicle_type)) {
|
||||
$dynamic_images_vehicle_type = (int)$dynamic_images_vehicle_type;
|
||||
if ($dynamic_images_vehicle_type < 0) {
|
||||
throw new Exception('dynamic_images_vehicle_type must be an integer >= 0');
|
||||
}
|
||||
}
|
||||
|
||||
// Add the object
|
||||
$tmp_id = self::add_object([
|
||||
'department' => $department,
|
||||
@@ -111,6 +129,8 @@ class department_selfserve_tasks_o extends db
|
||||
'description' => $description,
|
||||
'order_priority' => $order_priority,
|
||||
'services' => $services_names,
|
||||
'buttons' => $buttons_ids,
|
||||
...(!is_null($dynamic_images_vehicle_type) ? ['dynamic_images_vehicle_type' => $dynamic_images_vehicle_type] : []),
|
||||
]);
|
||||
$this->id = $tmp_id;
|
||||
self::getObjectProperties();
|
||||
@@ -129,6 +149,8 @@ class department_selfserve_tasks_o extends db
|
||||
$this->description = new object_property($this->table, $this->id, 'description', 'string', false);
|
||||
$this->order_priority = new object_property($this->table, $this->id, 'order_priority', 'int', false);
|
||||
$this->services = new object_property($this->table, $this->id, 'services', 'json', false);
|
||||
$this->buttons = new object_property($this->table, $this->id, 'buttons', 'json', false);
|
||||
$this->dynamic_images_vehicle_type = new object_property($this->table, $this->id, 'dynamic_images_vehicle_type', 'int', false);
|
||||
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'timestamp', false);
|
||||
$this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'timestamp', false);
|
||||
$this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'timestamp', false);
|
||||
@@ -151,9 +173,90 @@ class department_selfserve_tasks_o extends db
|
||||
'description' => (string)$this->description->value(),
|
||||
'order_priority' => (int)$this->order_priority->value(),
|
||||
'services' => (array)$this->services->value(),
|
||||
'buttons' => (array)$this->buttons->value(),
|
||||
'dynamic_images_vehicle_type' => (function($v){ return $v === null ? null : (int)$v; })($this->dynamic_images_vehicle_type->value()),
|
||||
// Timestamps
|
||||
'created_at' => (string)$this->created_at->value(),
|
||||
'updated_at' => (string)$this->updated_at->value(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize input for dynamic_images_vehicle_type into a nullable non-negative integer.
|
||||
* Accepts int, string (numeric), null, or empty string (treated as null).
|
||||
* @param mixed $input
|
||||
* @return int|null
|
||||
* @throws Exception on invalid format or negative values
|
||||
*/
|
||||
public static function normalizeVehicleTypeInput(mixed $input): ?int
|
||||
{
|
||||
if ($input === null) {
|
||||
return null;
|
||||
}
|
||||
if (is_string($input)) {
|
||||
$trim = trim($input);
|
||||
if ($trim === '' || strtolower($trim) === 'null') {
|
||||
return null;
|
||||
}
|
||||
if (ctype_digit($trim)) {
|
||||
$val = (int)$trim;
|
||||
} elseif (is_numeric($trim) && (int)$trim == $trim) {
|
||||
$val = (int)$trim;
|
||||
} else {
|
||||
throw new Exception('Invalid dynamic_images_vehicle_type value');
|
||||
}
|
||||
} elseif (is_int($input)) {
|
||||
$val = $input;
|
||||
} else {
|
||||
throw new Exception('Invalid dynamic_images_vehicle_type value');
|
||||
}
|
||||
if ($val < 0) {
|
||||
throw new Exception('dynamic_images_vehicle_type must be >= 0');
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
/**
|
||||
* Normalize mixed input for buttons into an array of integer IDs (>= 0).
|
||||
* Accepts:
|
||||
* - array of ints/strings
|
||||
* - JSON array string
|
||||
* - comma-separated string
|
||||
* @param mixed $input
|
||||
* @return array<int>
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function normalizeButtonsInput(mixed $input): array
|
||||
{
|
||||
$raw = $input;
|
||||
if (is_string($raw)) {
|
||||
$decoded = json_decode($raw, true);
|
||||
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
|
||||
$raw = $decoded;
|
||||
} else {
|
||||
$raw = array_filter(array_map(function ($s) { return trim((string)$s); }, explode(',', $raw)), fn($s) => $s !== '');
|
||||
}
|
||||
}
|
||||
if (!is_array($raw)) {
|
||||
throw new Exception('Invalid format for buttons. Expected array, JSON array, or comma-separated string of integers.');
|
||||
}
|
||||
$ids = [];
|
||||
foreach ($raw as $btn) {
|
||||
if (is_int($btn)) {
|
||||
$val = $btn;
|
||||
} elseif (is_string($btn) && ctype_digit($btn)) {
|
||||
$val = (int)$btn;
|
||||
} elseif (is_numeric($btn) && (int)$btn == $btn) {
|
||||
$val = (int)$btn;
|
||||
} else {
|
||||
throw new Exception('Invalid button id: ' . (is_scalar($btn) ? (string)$btn : gettype($btn)));
|
||||
}
|
||||
if ($val < 0) {
|
||||
throw new Exception('Button id must be >= 0: ' . $val);
|
||||
}
|
||||
$ids[] = $val;
|
||||
}
|
||||
// de-duplicate while preserving order
|
||||
$ids = array_values(array_unique($ids));
|
||||
return $ids;
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ class departmentLanesRoute
|
||||
'relay_in_id',
|
||||
'relay_out_id',
|
||||
'relay_machine_id',
|
||||
'dynamic_image_id',
|
||||
])
|
||||
->listObjectsWithPaginationIfSet(
|
||||
function ($department_lane) use ($user) {
|
||||
@@ -91,11 +92,18 @@ class departmentLanesRoute
|
||||
$relay_in_id = $response->getRequestParameter('relay_in_id') ?? null;
|
||||
$relay_out_id = $response->getRequestParameter('relay_out_id') ?? null;
|
||||
$relay_machine_id = $response->getRequestParameter('relay_machine_id') ?? null;
|
||||
$dynamic_image_id = $response->getRequestParameter('dynamic_image_id') ?? null;
|
||||
if ($dynamic_image_id !== null) {
|
||||
$did = (int)$dynamic_image_id;
|
||||
$this->requireType($did, $this->type_int());
|
||||
$this->requireMinValue($did, 1);
|
||||
$dynamic_image_id = $did;
|
||||
}
|
||||
// Remove spaces from the relay_in_id and relay_out_id
|
||||
// Check if the required fields are set
|
||||
if ($name && $department) {
|
||||
// Add the department lane
|
||||
(new department_lanes_o())->add((int)$department, (string)$name, $relay_in_id, $relay_out_id, $relay_machine_id);
|
||||
(new department_lanes_o())->add((int)$department, (string)$name, $relay_in_id, $relay_out_id, $relay_machine_id, $dynamic_image_id);
|
||||
// Return a success message
|
||||
$response->success('Department lane added');
|
||||
} else {
|
||||
@@ -133,6 +141,7 @@ class departmentLanesRoute
|
||||
$relay_in_id = $response->getRequestParameter('relay_in_id') ?? null;
|
||||
$relay_out_id = $response->getRequestParameter('relay_out_id') ?? null;
|
||||
$relay_machine_id = $response->getRequestParameter('relay_machine_id') ?? null;
|
||||
$dynamic_image_id = $response->getRequestParameter('dynamic_image_id') ?? null;
|
||||
|
||||
// Check what fields are set
|
||||
self::requireParameters(['id']);
|
||||
@@ -159,6 +168,17 @@ class departmentLanesRoute
|
||||
if (self::isParametersSet(['relay_machine_id'])) {
|
||||
$department_lane->relay_machine_id->set((string)$relay_machine_id);
|
||||
}
|
||||
if (self::isParametersSet(['dynamic_image_id'])) {
|
||||
$param = $response->getRequestParameter('dynamic_image_id');
|
||||
if ($param === null || $param === '' || (is_string($param) && strtolower($param) === 'null')) {
|
||||
$department_lane->dynamic_image_id->nullify();
|
||||
} else {
|
||||
$did = (int)$param;
|
||||
$this->requireType($did, $this->type_int());
|
||||
$this->requireMinValue($did, 1);
|
||||
$department_lane->dynamic_image_id->set($did);
|
||||
}
|
||||
}
|
||||
// Return a success message
|
||||
$response->success('Department lane updated');
|
||||
} else {
|
||||
|
||||
@@ -145,6 +145,28 @@ class departmentSelfserveTasksRoute
|
||||
}
|
||||
}
|
||||
|
||||
// Optional buttons
|
||||
$buttons_param = $response->isRequestParameterSet('buttons') ? $response->getRequestParameter('buttons') : null;
|
||||
$buttons_ids = null;
|
||||
if (!is_null($buttons_param)) {
|
||||
try {
|
||||
$buttons_ids = department_selfserve_tasks_o::normalizeButtonsInput($buttons_param);
|
||||
} catch (\Exception $e) {
|
||||
$response->error($e->getMessage(), 400);
|
||||
}
|
||||
}
|
||||
|
||||
// Optional dynamic_images_vehicle_type
|
||||
$vehicle_type_param = $response->isRequestParameterSet('dynamic_images_vehicle_type') ? $response->getRequestParameter('dynamic_images_vehicle_type') : null;
|
||||
$vehicle_type = null;
|
||||
if ($vehicle_type_param !== null) {
|
||||
try {
|
||||
$vehicle_type = department_selfserve_tasks_o::normalizeVehicleTypeInput($vehicle_type_param);
|
||||
} catch (\Exception $e) {
|
||||
$response->error($e->getMessage(), 400);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$department || !$lane || !$product || !$task || !$description) {
|
||||
$response->error('Missing required fields', 400);
|
||||
}
|
||||
@@ -164,6 +186,8 @@ class departmentSelfserveTasksRoute
|
||||
$description,
|
||||
$order_priority,
|
||||
$services_enums,
|
||||
$buttons_ids,
|
||||
$vehicle_type,
|
||||
);
|
||||
(new logs_o())->add('department_selfserve_tasks', 'global', 1, $user->id, 'ADD_TASK', 'User added a department self-serve task: ' . $task);
|
||||
$response->success($task_o->asArray());
|
||||
@@ -262,6 +286,36 @@ class departmentSelfserveTasksRoute
|
||||
}
|
||||
}
|
||||
|
||||
if (self::isParametersSet(['buttons'])) {
|
||||
$param = self::getParameter('buttons');
|
||||
if ($param === null) {
|
||||
// Explicitly clear buttons
|
||||
$task_o->buttons->set(null);
|
||||
} else {
|
||||
try {
|
||||
$ids = department_selfserve_tasks_o::normalizeButtonsInput($param);
|
||||
$task_o->buttons->set($ids);
|
||||
} catch (\Exception $e) {
|
||||
$response->error($e->getMessage(), 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Optional dynamic_images_vehicle_type update
|
||||
if (self::isParametersSet(['dynamic_images_vehicle_type'])) {
|
||||
$param = self::getParameter('dynamic_images_vehicle_type');
|
||||
if ($param === null) {
|
||||
$task_o->dynamic_images_vehicle_type->set(null);
|
||||
} else {
|
||||
try {
|
||||
$val = department_selfserve_tasks_o::normalizeVehicleTypeInput($param);
|
||||
$task_o->dynamic_images_vehicle_type->set($val);
|
||||
} catch (\Exception $e) {
|
||||
$response->error($e->getMessage(), 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(new logs_o())->add('department_selfserve_tasks', 'global', 1, $user->id, 'EDIT_TASK', 'User updated department self-serve task ID: ' . $id);
|
||||
$response->success($task_o->asArray());
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
if (!defined('WD')) { define('WD', dirname(__DIR__, 2)); }
|
||||
|
||||
require_once WD . '/classes/db.php';
|
||||
require_once WD . '/classes/object_property.php';
|
||||
require_once WD . '/traits/db_object_t.php';
|
||||
require_once WD . '/objects/department_lanes_o.php';
|
||||
require_once WD . '/modules/selfserve/helpers/selfserve_lane_status.php';
|
||||
|
||||
use modules\selfserve\helpers\selfserve_lane_status;
|
||||
|
||||
class TestDepartmentLane extends \objects\department_lanes_o
|
||||
{
|
||||
public function getLaneStatus(): selfserve_lane_status
|
||||
{
|
||||
// Return a deterministic status to avoid external dependencies
|
||||
return selfserve_lane_status::AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
function assert_true($cond, $msg)
|
||||
{
|
||||
if ($cond) {
|
||||
echo "✔ $msg\n";
|
||||
} else {
|
||||
echo "✘ $msg\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize a lane object in fake/id<0 mode to avoid DB access
|
||||
$lane = new TestDepartmentLane();
|
||||
$lane->structure(); // ensure table is set
|
||||
$lane->id = -1; // enable fake value mode in object_property
|
||||
$lane->getObjectProperties();
|
||||
|
||||
// Set fake values
|
||||
$lane->department->set(7);
|
||||
$lane->name->set('Test Lane');
|
||||
$lane->relay_in_id->set('shelly-relay-in-001');
|
||||
$lane->relay_out_id->set('shelly-relay-out-001');
|
||||
$lane->relay_machine_id->set('shelly-relay-machine-001');
|
||||
$lane->dynamic_image_id->set(42);
|
||||
$lane->created_at->set('2026-01-01 00:00:00');
|
||||
$lane->updated_at->set('2026-01-02 00:00:00');
|
||||
|
||||
// Serialize and validate
|
||||
$arr = $lane->asArray();
|
||||
|
||||
assert_true(array_key_exists('dynamic_image_id', $arr), 'dynamic_image_id is present in lane serialization');
|
||||
assert_true($arr['dynamic_image_id'] === 42, 'dynamic_image_id matches the set integer value');
|
||||
|
||||
// Some basic sanity checks to ensure no regressions
|
||||
assert_true($arr['department'] === 7, 'department matches');
|
||||
assert_true($arr['name'] === 'Test Lane', 'name matches');
|
||||
|
||||
echo "DepartmentLaneDynamicImageIdTest completed.\n";
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace classes {
|
||||
// Minimal stubs to satisfy class loading without full app bootstrap
|
||||
class db {}
|
||||
class object_property {
|
||||
public function __construct(...$args) {}
|
||||
public function value() { return null; }
|
||||
public function set($v) {}
|
||||
}
|
||||
}
|
||||
|
||||
namespace traits {
|
||||
trait db_object_t {}
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Lightweight bootstrap for CLI execution without full index.php
|
||||
if (!defined('WD')) {
|
||||
define('WD', __DIR__ . '/../../');
|
||||
}
|
||||
|
||||
require_once WD . 'objects/department_selfserve_tasks_o.php';
|
||||
|
||||
use objects\department_selfserve_tasks_o;
|
||||
|
||||
function ok($message): void { echo "\n\033[32m✔ $message\033[0m\n"; }
|
||||
function fail($message): void { echo "\n\033[31m✖ $message\033[0m\n"; }
|
||||
|
||||
echo "\nButtonsNormalizationTest starting...\n";
|
||||
|
||||
// 1) Array input with ints and numeric strings
|
||||
try {
|
||||
$result = department_selfserve_tasks_o::normalizeButtonsInput([1, '2', 3]);
|
||||
if ($result === [1, 2, 3]) {
|
||||
ok('Array input normalized correctly');
|
||||
} else {
|
||||
fail('Array input normalization mismatch: ' . json_encode($result));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
fail('Array input threw unexpectedly: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
// 2) JSON string input with duplicates and zero
|
||||
try {
|
||||
$result = department_selfserve_tasks_o::normalizeButtonsInput('[4,5,5,0]');
|
||||
if ($result === [4,5,0]) {
|
||||
ok('JSON input normalized with duplicates removed');
|
||||
} else {
|
||||
fail('JSON input normalization mismatch: ' . json_encode($result));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
fail('JSON input threw unexpectedly: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
// 3) CSV string input
|
||||
try {
|
||||
$result = department_selfserve_tasks_o::normalizeButtonsInput('6, 7 ,8');
|
||||
if ($result === [6,7,8]) {
|
||||
ok('CSV input normalized correctly');
|
||||
} else {
|
||||
fail('CSV input normalization mismatch: ' . json_encode($result));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
fail('CSV input threw unexpectedly: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
// 4) Invalid input should throw
|
||||
$thrown = false;
|
||||
try {
|
||||
department_selfserve_tasks_o::normalizeButtonsInput('["a", 2]');
|
||||
} catch (\Exception $e) {
|
||||
$thrown = true;
|
||||
ok('Invalid input correctly threw exception: ' . $e->getMessage());
|
||||
}
|
||||
if (!$thrown) {
|
||||
fail('Expected exception for invalid input, but none was thrown');
|
||||
}
|
||||
|
||||
echo "\nButtonsNormalizationTest completed.\n";
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace classes {
|
||||
// Minimal stubs to satisfy class loading without full app bootstrap
|
||||
class db {}
|
||||
class object_property {
|
||||
public function __construct(...$args) {}
|
||||
public function value() { return null; }
|
||||
public function set($v) {}
|
||||
}
|
||||
}
|
||||
|
||||
namespace traits {
|
||||
trait db_object_t {}
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Lightweight bootstrap for CLI execution without full index.php
|
||||
if (!defined('WD')) {
|
||||
define('WD', __DIR__ . '/../../');
|
||||
}
|
||||
|
||||
require_once WD . 'objects/department_selfserve_tasks_o.php';
|
||||
|
||||
use objects\department_selfserve_tasks_o;
|
||||
|
||||
function ok($message): void { echo "\n\033[32m✔ $message\033[0m\n"; }
|
||||
function fail($message): void { echo "\n\033[31m✖ $message\033[0m\n"; }
|
||||
|
||||
echo "\nDynamicImagesVehicleTypeNormalizationTest starting...\n";
|
||||
|
||||
// 1) Integer input
|
||||
try {
|
||||
$v = department_selfserve_tasks_o::normalizeVehicleTypeInput(3);
|
||||
if ($v === 3) { ok('Integer input accepted'); } else { fail('Integer input mismatch: ' . var_export($v, true)); }
|
||||
} catch (\Exception $e) { fail('Integer input threw: ' . $e->getMessage()); }
|
||||
|
||||
// 2) Numeric string input
|
||||
try {
|
||||
$v = department_selfserve_tasks_o::normalizeVehicleTypeInput('4');
|
||||
if ($v === 4) { ok('Numeric string input accepted'); } else { fail('Numeric string mismatch: ' . var_export($v, true)); }
|
||||
} catch (\Exception $e) { fail('Numeric string input threw: ' . $e->getMessage()); }
|
||||
|
||||
// 3) Trimmed numeric string with spaces
|
||||
try {
|
||||
$v = department_selfserve_tasks_o::normalizeVehicleTypeInput(' 5 ');
|
||||
if ($v === 5) { ok('Trimmed numeric string input accepted'); } else { fail('Trimmed numeric string mismatch: ' . var_export($v, true)); }
|
||||
} catch (\Exception $e) { fail('Trimmed numeric string input threw: ' . $e->getMessage()); }
|
||||
|
||||
// 4) Null input -> null
|
||||
try {
|
||||
$v = department_selfserve_tasks_o::normalizeVehicleTypeInput(null);
|
||||
if ($v === null) { ok('Null input returns null'); } else { fail('Null input mismatch: ' . var_export($v, true)); }
|
||||
} catch (\Exception $e) { fail('Null input threw: ' . $e->getMessage()); }
|
||||
|
||||
// 5) Empty string -> null
|
||||
try {
|
||||
$v = department_selfserve_tasks_o::normalizeVehicleTypeInput('');
|
||||
if ($v === null) { ok('Empty string treated as null'); } else { fail('Empty string mismatch: ' . var_export($v, true)); }
|
||||
} catch (\Exception $e) { fail('Empty string threw: ' . $e->getMessage()); }
|
||||
|
||||
// 6) Negative value should throw
|
||||
$thrown = false;
|
||||
try {
|
||||
department_selfserve_tasks_o::normalizeVehicleTypeInput(-1);
|
||||
} catch (\Exception $e) {
|
||||
$thrown = true; ok('Negative value correctly threw: ' . $e->getMessage());
|
||||
}
|
||||
if (!$thrown) { fail('Expected exception for negative value, but none was thrown'); }
|
||||
|
||||
// 7) Non-numeric string should throw
|
||||
$thrown = false;
|
||||
try {
|
||||
department_selfserve_tasks_o::normalizeVehicleTypeInput('abc');
|
||||
} catch (\Exception $e) {
|
||||
$thrown = true; ok('Non-numeric string correctly threw: ' . $e->getMessage());
|
||||
}
|
||||
if (!$thrown) { fail('Expected exception for non-numeric string, but none was thrown'); }
|
||||
|
||||
echo "\nDynamicImagesVehicleTypeNormalizationTest completed.\n";
|
||||
}
|
||||
Reference in New Issue
Block a user