394 lines
19 KiB
PHP
394 lines
19 KiB
PHP
<?php
|
|
|
|
namespace routes;
|
|
|
|
use classes\authentication;
|
|
use classes\response;
|
|
use dynamicimages\images\machine_1;
|
|
use objects\categories_o;
|
|
use objects\department_lanes_o;
|
|
use objects\department_selfserve_tasks_o;
|
|
use objects\logs_o;
|
|
use traits\route_t;
|
|
|
|
class departmentLanesRoute
|
|
{
|
|
use route_t;
|
|
|
|
public function run(): void
|
|
{
|
|
$this->get('/department/lanes', function () {
|
|
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$this->requirePermission('list_department_lanes');
|
|
// Get the user object
|
|
$user = (new authentication())->get_user();
|
|
// Check if the request was successful
|
|
if ($user) {
|
|
// Check if the id parameter is set
|
|
if (self::isParametersSet(['id'])) {
|
|
// If it is, return the department lane with that id
|
|
$department_lane = (new department_lanes_o())->select((int)$response->getRequestParameter('id'));
|
|
// Check if the department lane exists
|
|
if (!$department_lane->exists()) {
|
|
// Return an error
|
|
$response->error('Department lane not found', 404);
|
|
}
|
|
// Log the incident
|
|
(new logs_o())->add('department_lanes', 'global', 1, $user->id, 'VIEW_DEPARTMENT_LANE', 'User viewed department lane with id ' . $department_lane->id);
|
|
// Return the department lane
|
|
$response->success(
|
|
$department_lane->asArray()
|
|
);
|
|
}
|
|
// Log the incident
|
|
(new logs_o())->add('department_lanes', 'global', 1, $user->id, 'LIST_DEPARTMENT_LANES', 'User listed department lanes');
|
|
// Return the list of departments
|
|
$response->success(
|
|
(new department_lanes_o())
|
|
->setSearchableFields([
|
|
// The fields that can be searched. This would otherwise make it possible to get secret information from the database, simply by searching for it and getting the result count back
|
|
'id',
|
|
'name',
|
|
'department',
|
|
'relay_in_id',
|
|
'relay_out_id',
|
|
'relay_machine_id',
|
|
'relay_machine_program_picker_id',
|
|
'relay_machine_cleaner_id',
|
|
'dynamic_image_id',
|
|
'machine_type_id',
|
|
])
|
|
->listObjectsWithPaginationIfSet(
|
|
function ($department_lane) use ($user) {
|
|
// Create the department lane object
|
|
$department_lane_o = (new department_lanes_o())->select((int)$department_lane['id']);
|
|
// Return the object as an array
|
|
return $department_lane_o->asArray();
|
|
}
|
|
)
|
|
);
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('department_lanes', 'global', 1, 0, 'LIST_DEPARTMENT_LANES', 'User tried to list department lanes without being logged in');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'list_department_lanes' => 'List all department lanes'
|
|
]
|
|
);
|
|
|
|
/**
|
|
* Generate dynamic image for a department lane (machine UI)
|
|
*
|
|
* Query parameters:
|
|
* - department (int, required)
|
|
* - lane (int, required)
|
|
* - buttons (array|json|csv, optional) → highlighted button IDs (0-indexed)
|
|
* - current_step (int >= 0, optional) → current click/step indicator
|
|
* - only_current_step (bool/int, optional) → if true, only draw current step highlight
|
|
* - vehicle_type (int|null, optional) → normalized but currently not used by machine_1
|
|
*
|
|
* Response: image/png
|
|
*/
|
|
$this->get('/department/lanes/dynamic-image', function () {
|
|
global $response;
|
|
// Reuse listing permission; viewing image is tied to lane visibility
|
|
// Authenticated user and department access validation
|
|
//$this->requirePermission('view_department_lane_image');
|
|
|
|
|
|
// Required params
|
|
self::requireParameters(['department', 'lane']);
|
|
$department_id = (int) self::getParameter('department');
|
|
$lane_id = (int) self::getParameter('lane');
|
|
self::requireType($department_id, self::type_int());
|
|
self::requireType($lane_id, self::type_int());
|
|
self::requireMinValue($department_id, 1);
|
|
self::requireMinValue($lane_id, 1);
|
|
|
|
|
|
// Load lane and verify it belongs to department
|
|
$lane = (new department_lanes_o())->select($lane_id);
|
|
if (!$lane->exists()) {
|
|
$response->error('Department lane not found', 404);
|
|
}
|
|
if ((int)$lane->department->value() !== $department_id) {
|
|
$response->error('Lane does not belong to the specified department', 400);
|
|
}
|
|
|
|
// Resolve dynamic image id → class (support id=1 for now)
|
|
$dynamic_image_id = $lane->dynamic_image_id->value();
|
|
if ($dynamic_image_id === null) {
|
|
$response->error('No dynamic image configured for this lane', 404);
|
|
}
|
|
$dynamic_image_id = (int)$dynamic_image_id;
|
|
|
|
// Parse optional params
|
|
$buttons = null;
|
|
if ($response->isRequestParameterSet('buttons')) {
|
|
$buttons = $response->getRequestParameter('buttons');
|
|
try {
|
|
$buttons = department_selfserve_tasks_o::normalizeButtonsInput($buttons);
|
|
} catch (\Exception $e) {
|
|
$response->error('Invalid buttons parameter: ' . $e->getMessage(), 400);
|
|
}
|
|
}
|
|
|
|
$current_step = 0;
|
|
if ($response->isRequestParameterSet('current_step')) {
|
|
$cs = (int)$response->getRequestParameter('current_step');
|
|
self::requireMinValue($cs, 0);
|
|
$current_step = $cs;
|
|
}
|
|
|
|
$only_current_step = false;
|
|
if ($response->isRequestParameterSet('only_current_step')) {
|
|
$val = $response->getRequestParameter('only_current_step');
|
|
// Accept true/false, 1/0, '1'/'0'
|
|
$only_current_step = in_array(strtolower((string)$val), ['1', 'true', 'yes', 'on'], true);
|
|
}
|
|
|
|
// Vehicle type (normalized; may be unused by concrete image class at present)
|
|
$vehicle_type = null;
|
|
if ($response->isRequestParameterSet('vehicle_type')) {
|
|
try {
|
|
$vehicle_type = department_selfserve_tasks_o::normalizeVehicleTypeInput($response->getRequestParameter('vehicle_type'));
|
|
} catch (\Exception $e) {
|
|
$response->error('Invalid vehicle_type parameter: ' . $e->getMessage(), 400);
|
|
}
|
|
}
|
|
|
|
// Thumb position (normalized)
|
|
$thumb_position = null;
|
|
if ($response->isRequestParameterSet('thumb_position')) {
|
|
$thumb_position = (int)$response->getRequestParameter('thumb_position');
|
|
self::requireMinValue($thumb_position, 1);
|
|
self::requireMaxValue($thumb_position, 12);
|
|
}
|
|
|
|
// Cache check
|
|
$cacheKey = null;
|
|
if (defined('redis')) {
|
|
$cacheParams = [
|
|
'dynamic_image_id' => $dynamic_image_id,
|
|
'buttons' => $buttons,
|
|
'current_step' => $current_step,
|
|
'only_current_step' => (bool)$only_current_step,
|
|
'vehicle_type' => $vehicle_type,
|
|
'thumb_position' => $thumb_position,
|
|
];
|
|
$cacheKey = 'dynamic_image_v2:' . md5(json_encode($cacheParams));
|
|
$cachedImage = redis->get($cacheKey);
|
|
if ($cachedImage) {
|
|
header('Content-Type: image/png');
|
|
header('Content-Length: ' . strlen($cachedImage));
|
|
echo $cachedImage;
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Instantiate and configure the image class based on dynamic_image_id
|
|
switch ($dynamic_image_id) {
|
|
case 1:
|
|
$image = new machine_1();
|
|
// Require thumb_position for machine_1
|
|
if ($thumb_position === null) {
|
|
$response->error('thumb_position parameter is required for this dynamic image', 400);
|
|
}
|
|
$image->thumb_position = $thumb_position;
|
|
break;
|
|
default:
|
|
$response->error('Unsupported dynamic image id: ' . $dynamic_image_id, 400);
|
|
}
|
|
|
|
// Apply parameters
|
|
if (is_array($buttons)) {
|
|
$image->highlighted_buttons = $buttons;
|
|
}
|
|
$image->current_step = $current_step;
|
|
$image->only_generate_current_step = (bool)$only_current_step;
|
|
// Note: $vehicle_type currently not used by machine_1; reserved for future images.
|
|
|
|
// Compose and serve the image
|
|
try {
|
|
$image->setup();
|
|
|
|
// If caching is enabled, we need to capture the output or use export
|
|
if ($cacheKey && defined('redis')) {
|
|
$dataUri = $image->exportAsBase64('png');
|
|
if (preg_match('/^data:image\/png;base64,(.*)$/', $dataUri, $matches)) {
|
|
$imageData = base64_decode($matches[1]);
|
|
if ($imageData !== false) {
|
|
redis->setEx($cacheKey, $imageData, 86400); // Cache for 24 hours
|
|
header('Content-Type: image/png');
|
|
header('Content-Length: ' . strlen($imageData));
|
|
echo $imageData;
|
|
exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
$image->servePicture('png');
|
|
exit; // Ensure no extra output is appended
|
|
} catch (\Exception $e) {
|
|
$response->error('Failed to generate image: ' . $e->getMessage(), 500);
|
|
}
|
|
}, [
|
|
'list_department_lanes' => 'View dynamic image for a department lane',
|
|
]);
|
|
|
|
$this->post('/department/lanes', function () {
|
|
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$this->requirePermission('add_department_lane');
|
|
// Get the user object
|
|
$user = (new authentication())->get_user();
|
|
// Check if the request was successful
|
|
if ($user) {
|
|
// Log the incident
|
|
(new logs_o())->add('department_lanes', 'global', 1, $user->id, 'ADD_DEPARTMENT_LANE', 'User added a department lane');
|
|
// Get the request data
|
|
$name = $response->getRequestParameter('name') ?? null;
|
|
$department = $response->getRequestParameter('department') ?? null;
|
|
$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;
|
|
$relay_machine_program_picker_id = $response->getRequestParameter('relay_machine_program_picker_id') ?? null;
|
|
$relay_machine_cleaner_id = $response->getRequestParameter('relay_machine_cleaner_id') ?? null;
|
|
|
|
$dynamic_image_id = $response->getRequestParameter('dynamic_image_id') ?? null;
|
|
$machine_type_id = $response->getRequestParameter('machine_type_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;
|
|
}
|
|
if ($machine_type_id !== null && $machine_type_id !== '' && strtolower((string)$machine_type_id) !== 'null') {
|
|
$machine_type_id = (int)$machine_type_id;
|
|
$this->requireType($machine_type_id, $this->type_int());
|
|
$this->requireMinValue($machine_type_id, 1);
|
|
} else {
|
|
$machine_type_id = null;
|
|
}
|
|
// 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, $relay_machine_program_picker_id, $relay_machine_cleaner_id, $dynamic_image_id, $machine_type_id);
|
|
// Return a success message
|
|
$response->success('Department lane added');
|
|
} else {
|
|
// Return an error
|
|
$response->error('Missing required fields', 400);
|
|
}
|
|
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('department_lanes', 'global', 1, 0, 'ADD_DEPARTMENT_LANE', 'User tried to add a department lane without being logged in');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'add_department_lane' => 'Add a department lane'
|
|
]
|
|
);
|
|
|
|
$this->put('/department/lanes', function () {
|
|
|
|
// Require the user to be logged in
|
|
global $response;
|
|
$this->requirePermission('edit_department_lane');
|
|
// Get the user object
|
|
$user = (new authentication())->get_user();
|
|
// Check if the request was successful
|
|
if ($user) {
|
|
// Log the incident
|
|
(new logs_o())->add('department_lanes', 'global', 1, $user->id, 'EDIT_DEPARTMENT_LANE', 'User edited a department lane');
|
|
// Get the request data
|
|
$id = $response->getRequestParameter('id') ?? null;
|
|
$name = $response->getRequestParameter('name') ?? null;
|
|
$department = $response->getRequestParameter('department') ?? null;
|
|
$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;
|
|
$relay_machine_program_picker_id = $response->getRequestParameter('relay_machine_program_picker_id') ?? null;
|
|
$relay_machine_cleaner_id = $response->getRequestParameter('relay_machine_cleaner_id') ?? null;
|
|
$dynamic_image_id = $response->getRequestParameter('dynamic_image_id') ?? null;
|
|
$machine_type_id = $response->getRequestParameter('machine_type_id') ?? null;
|
|
|
|
// Check what fields are set
|
|
self::requireParameters(['id']);
|
|
// Get the department lane object
|
|
$department_lane = (new department_lanes_o())->select((int)$id);
|
|
// Check if the department lane exists
|
|
if (!$department_lane->exists()) {
|
|
// Return an error
|
|
$response->error('Department lane not found', 404);
|
|
}
|
|
// Update the department lane fields that are set
|
|
if (self::isParametersSet(['name'])) {
|
|
$department_lane->name->set($name);
|
|
}
|
|
if (self::isParametersSet(['department'])) {
|
|
$department_lane->department->set((int)$department);
|
|
}
|
|
if (self::isParametersSet(['relay_in_id'])) {
|
|
$department_lane->relay_in_id->set((string)$relay_in_id);
|
|
}
|
|
if (self::isParametersSet(['relay_out_id'])) {
|
|
$department_lane->relay_out_id->set((string)$relay_out_id);
|
|
}
|
|
if (self::isParametersSet(['relay_machine_id'])) {
|
|
$department_lane->relay_machine_id->set((string)$relay_machine_id);
|
|
}
|
|
if (self::isParametersSet(['relay_machine_program_picker_id'])) {
|
|
$department_lane->relay_machine_program_picker_id->set((string)$relay_machine_program_picker_id);
|
|
}
|
|
if (self::isParametersSet(['relay_machine_cleaner_id'])) {
|
|
$department_lane->relay_machine_cleaner_id->set((string)$relay_machine_cleaner_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);
|
|
}
|
|
}
|
|
if (self::isParametersSet(['machine_type_id'])) {
|
|
$param = $machine_type_id;
|
|
if ($param === null || $param === '' || (is_string($param) && strtolower($param) === 'null')) {
|
|
$department_lane->machine_type_id->nullify();
|
|
} else {
|
|
$machineTypeId = (int)$param;
|
|
$this->requireType($machineTypeId, $this->type_int());
|
|
$this->requireMinValue($machineTypeId, 1);
|
|
$department_lane->machine_type_id->set($machineTypeId);
|
|
}
|
|
}
|
|
// Return a success message
|
|
$response->success('Department lane updated');
|
|
} else {
|
|
// Log the incident
|
|
(new logs_o())->add('department_lanes', 'global', 1, 0, 'EDIT_DEPARTMENT_LANE', 'User tried to edit a department lane without being logged in');
|
|
// Return an error
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
},
|
|
[
|
|
'edit_department_lane' => 'Edit a department lane'
|
|
]
|
|
);
|
|
}
|
|
}
|