Files
api/services/nginx/app/objects/department_variables_o.php
T
Jeppe B da0113e3ed Auto-disable department self-serve at opening (#323)
Auto-disable department self-serve at opening
2026-07-28 18:03:05 +02:00

264 lines
7.8 KiB
PHP

<?php
namespace objects;
use classes\db;
use classes\object_property;
use Exception;
use traits\db_object_t;
class department_variables_o extends db
{
use db_object_t;
public int $department_id;
public object_property $variable;
public object_property $value;
public object_property $created_at;
public function structure(): void
{
$this->setTable('department_variables');
}
/**
* Set a department variable
* @param string $variable The variable name
* @param string $value The variable value
* @return void
*
* @throws Exception If the object was not created successfully
*/
public function set(string $variable, mixed $value): void
{
self::requireDepartmentId();
// Check if the variable already exists
$isAlreadyDefinedId = self::getFieldsWhere([
'department_id' => $this->department_id,
'variable' => $variable
], ['id']);
// Update the variable if it already exists
if ($isAlreadyDefinedId) {
$this->id = $isAlreadyDefinedId[0]['id'];
$this->getObjectProperties();
$this->value->set($value);
return;
}
// Add the variable
$tmp_id = self::add_object([
'department_id' => $this->department_id,
'variable' => $variable,
'value' => $value
]);
$this->id = $tmp_id;
self::getObjectProperties();
self::objectChanged();
if (!$this->id) {
throw new Exception('The variable was not created successfully.');
}
}
public static function withSelfServeTransitionLock(
int $departmentId,
callable $callback,
int $timeoutSeconds = 5
): mixed {
if ($departmentId <= 0) {
throw new \InvalidArgumentException('A valid department is required for the self-serve transition lock.');
}
$lockName = 'selfserve:department-transition:' . $departmentId;
if (!self::acquireSelfServeTransitionLock($lockName, max(0, $timeoutSeconds))) {
throw new \RuntimeException('The department self-serve transition is already in progress.');
}
try {
return $callback();
} finally {
try {
self::releaseSelfServeTransitionLock($lockName);
} catch (\Throwable) {
}
}
}
private static function acquireSelfServeTransitionLock(string $lockName, int $timeoutSeconds): bool
{
global $db;
$statement = $db->prepare('SELECT GET_LOCK(?, ?) AS acquired');
if ($statement === false) {
throw new \RuntimeException('Could not prepare the department self-serve transition lock.');
}
try {
$statement->bind_param('si', $lockName, $timeoutSeconds);
$statement->execute();
$result = $statement->get_result();
$row = $result instanceof \mysqli_result ? $result->fetch_assoc() : null;
return (int)($row['acquired'] ?? 0) === 1;
} finally {
$statement->close();
}
}
private static function releaseSelfServeTransitionLock(string $lockName): void
{
global $db;
$statement = $db->prepare('SELECT RELEASE_LOCK(?) AS released');
if ($statement === false) {
throw new \RuntimeException('Could not prepare the department self-serve transition lock release.');
}
try {
$statement->bind_param('s', $lockName);
$statement->execute();
} finally {
$statement->close();
}
}
/**
* Require the department ID to be set, and throw an exception if it is not
* @throws Exception If the department ID is not set.
*/
public function requireDepartmentId(): void
{
if (!$this->department_id) {
throw new Exception('The department ID is not set.');
}
}
/**
* Get the department variable by ID
* @throws Exception If the department ID is not set
*/
public function getObjectProperties(): void
{
self::requireDepartmentId();
$this->variable = new object_property($this->table, $this->id, 'variable', 'string', false);
$this->value = new object_property($this->table, $this->id, 'value', 'string', false);
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'string', false);
}
public function objectChanged(): void
{
//TODO: Add cache invalidation
}
/**
* List all department variables
* @throws Exception If the department ID is not set
*/
public function list(): array
{
self::requireDepartmentId();
$variables = self::getFieldsWhere([
'department_id' => $this->department_id
], ['id']);
$result = [];
foreach ( $variables as $variable ) {
$tmp = new department_variables_o();
$tmp->select($variable['id']);
$result[] = $tmp->asArray();
}
return $result;
}
/**
* Get the department variable by name
* @throws Exception If the object was not selected
*/
public function asArray(): array
{
self::requireSelected();
return [
'id' => (int)$this->id,
'department_id' => (int)$this->department_id,
'variable' => (string)$this->variable->value(),
'value' => (string)$this->value->value(),
'created_at' => (string)$this->created_at->value(),
];
}
/**
* Get a department variable
* @param string $variable The variable name
* @return null If the variable is not set
* @return mixed The variable value
* @throws Exception If the department ID is not set
*/
public function getVariable(string $variable): mixed
{
self::requireDepartmentId();
$variable = self::getFieldsWhere([
'department_id' => $this->department_id,
'variable' => $variable
], ['value']);
if (!$variable) {
return null;
}
// Check if the variable is 'false' or 'true'
if ($variable[0]['value'] === 'false') {
return false;
}
if ($variable[0]['value'] === 'true') {
return true;
}
return $variable[0]['value'];
}
/**
* Check if a department variable is set
* @param string $variable The variable name
* @return bool If the variable is set
* @throws Exception If the department ID is not set
*/
public function isSet(string $variable): bool
{
self::requireDepartmentId();
$variable = self::getFieldsWhere([
'department_id' => $this->department_id,
'variable' => $variable
], ['id']);
return (bool)count($variable);
}
/**
* Nullify a department variable
* @param string $variable The variable name
* @return void If the variable was nullified
* @throws Exception If the object was not selected
* @throws Exception If the department ID is not set
*/
public function nullify(string $variable): void
{
self::requireDepartmentId();
$variable = self::getFieldsWhere([
'department_id' => $this->department_id,
'variable' => $variable
], ['id']);
if ($variable) {
$tmp = new department_variables_o();
$tmp->select($variable[0]['id']);
$tmp->requireSelected();
$tmp->delete();
}
}
/**
* Select a department
* @param int $id The department ID
* @return self
*/
public function selectDepartment(int $id): self
{
$this->department_id = $id;
return $this;
}
}