197 lines
7.1 KiB
PHP
197 lines
7.1 KiB
PHP
<?php
|
|
|
|
namespace classes;
|
|
|
|
class object_property
|
|
{
|
|
public int $id; // The table of the objects in the database (e.g. users)
|
|
private string $table; // The id of the object in the database
|
|
private string $column; // The column name of the field in the database table (e.g. id, name, email)
|
|
private string $type; // The data type of the field in the database table (e.g. int, varchar, text)
|
|
private bool $required; // Whether the field is required or not
|
|
private mixed $default; // The default value of the field
|
|
private mixed $fake_value; // The fake value of the field, used for testing purposes (When the object id is -1)
|
|
|
|
public function __construct(string $table, int $id, string $column, string $type, bool $required = false, mixed $default = null)
|
|
{
|
|
$this->table = $table;
|
|
$this->id = $id;
|
|
$this->column = $column;
|
|
$this->type = $type;
|
|
$this->required = $required;
|
|
$this->default = $default;
|
|
}
|
|
|
|
public function __toString(): string
|
|
{
|
|
// Return the value of the field in the database table
|
|
return $this->value();
|
|
}
|
|
|
|
public function requireSelected(): void
|
|
{
|
|
// Check if the object is selected
|
|
// This is a placeholder function. In a real implementation, this would check if the object
|
|
if (!isset($this->id)) {
|
|
throw new \RuntimeException("Object not selected");
|
|
}
|
|
}
|
|
|
|
private function getCacheKey(): string
|
|
{
|
|
return "obj_prop:{$this->table}:{$this->id}:{$this->column}";
|
|
}
|
|
|
|
/**
|
|
* Get the value of the field in the database table
|
|
* @return mixed The value of the field in the database table
|
|
*/
|
|
public function value(): mixed
|
|
{
|
|
self::requireSelected();
|
|
if ($this->id < 0) {
|
|
// If the object id is less than 0, return the fake value
|
|
return $this->fake_value ?? $this->default;
|
|
}
|
|
|
|
$cacheKey = $this->getCacheKey();
|
|
if (defined('redis')) {
|
|
$cachedValue = redis->get($cacheKey);
|
|
if ($cachedValue !== null) {
|
|
if ($cachedValue === '___NULL___') {
|
|
return null;
|
|
}
|
|
if ($this->type === 'json') {
|
|
return json_decode($cachedValue, true);
|
|
}
|
|
return $cachedValue;
|
|
}
|
|
}
|
|
|
|
// Get the value of the field in the database table
|
|
global $db;
|
|
// Sanitize the id to prevent SQL injection
|
|
$this->id = (int)$this->id;
|
|
// Check if the id is valid
|
|
if ($this->id <= 0) {
|
|
throw new \InvalidArgumentException("Invalid ID: $this->id");
|
|
}
|
|
// Check if the table and column are valid
|
|
if (empty($this->table) || empty($this->column)) {
|
|
throw new \InvalidArgumentException("Table or column cannot be empty");
|
|
}
|
|
// Check if the type is valid
|
|
if (!in_array($this->type, ['int', 'varchar', 'text', 'date', 'datetime', 'string', 'timestamp', 'boolean', 'bool', 'float', 'json'])) {
|
|
throw new \InvalidArgumentException("Invalid type: $this->type");
|
|
}
|
|
$sql = "SELECT $this->column FROM $this->table WHERE id = $this->id";
|
|
$result = $db->query($sql);
|
|
$row = $db->fetch_assoc($result);
|
|
if (empty($row)) {
|
|
throw new \RuntimeException("No record found for column '$this->column' in table '$this->table' with ID $this->id");
|
|
}
|
|
|
|
$value = $row[$this->column];
|
|
|
|
if (defined('redis')) {
|
|
$toCache = $value;
|
|
if ($value === null) {
|
|
$toCache = '___NULL___';
|
|
}
|
|
redis->set($cacheKey, (string)$toCache);
|
|
redis->expire($cacheKey, 3600); // Cache for 1 hour
|
|
}
|
|
|
|
// If the type is set to json, decode it.
|
|
if ($this->type === 'json' && $value !== null) {
|
|
return json_decode($value, true);
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Set the value of the field in the database table
|
|
* @param mixed $value The value of the field in the database table
|
|
*/
|
|
public function set(mixed $value): void
|
|
{
|
|
if ($this->id < 0) {
|
|
// If the object id is less than 0, set the fake value
|
|
$this->fake_value = $value;
|
|
return;
|
|
}
|
|
// Set the value of the field in the database table
|
|
global /** @var db $db */
|
|
$db;
|
|
|
|
// If the value is null, set it to null
|
|
if ($value === null) {
|
|
$sql = "UPDATE $this->table SET $this->column = NULL WHERE id = $this->id";
|
|
} // If the value is an integer, set it to the integer value
|
|
elseif (is_int($value)) {
|
|
$sql = "UPDATE $this->table SET $this->column = $value WHERE id = $this->id";
|
|
} // If the value is a float, set it to the float value
|
|
elseif (is_float($value)) {
|
|
$sql = "UPDATE $this->table SET $this->column = $value WHERE id = $this->id";
|
|
} // If the value is a boolean, store as 1/0
|
|
elseif (is_bool($value)) {
|
|
$sql = "UPDATE $this->table SET $this->column = " . ($value ? 1 : 0) . " WHERE id = $this->id";
|
|
} // If the column type is json, JSON-encode the value
|
|
elseif ($this->type === 'json') {
|
|
$encoded = json_encode($value, JSON_UNESCAPED_UNICODE);
|
|
$encoded = $db->escape_string($encoded);
|
|
$sql = "UPDATE $this->table SET $this->column = '$encoded' WHERE id = $this->id";
|
|
} // If the value is a string, escape it
|
|
elseif (is_string($value)) {
|
|
$value = $db->escape_string($value);
|
|
$sql = "UPDATE $this->table SET $this->column = '$value' WHERE id = $this->id";
|
|
} else {
|
|
// Unsupported type for non-json columns
|
|
$type = gettype($value);
|
|
throw new \InvalidArgumentException("Unsupported value type '$type' for {$this->table}.{$this->column} (expected scalar or json-capable)");
|
|
}
|
|
$db->query($sql);
|
|
|
|
if (defined('redis')) {
|
|
redis->delete($this->getCacheKey());
|
|
}
|
|
try {
|
|
system_search_cache::markDirtyTable($this->table);
|
|
} catch (\Throwable) {
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Alias for set()
|
|
* @param mixed $value The value of the field in the database table
|
|
*/
|
|
public function update(mixed $value): void
|
|
{
|
|
$this->set($value);
|
|
}
|
|
|
|
/**
|
|
* Nullify the value of the field in the database table
|
|
*/
|
|
public function nullify(): void
|
|
{
|
|
if ($this->id < 0) {
|
|
// If the object id is less than 0, set the fake value to null
|
|
$this->fake_value = null;
|
|
return;
|
|
}
|
|
// Set the value of the field in the database table to null
|
|
global /** @var db $db */
|
|
$db;
|
|
$sql = "UPDATE $this->table SET $this->column = NULL WHERE id = $this->id";
|
|
$db->query($sql);
|
|
if (defined('redis')) {
|
|
redis->delete($this->getCacheKey());
|
|
}
|
|
try {
|
|
system_search_cache::markDirtyTable($this->table);
|
|
} catch (\Throwable) {
|
|
}
|
|
}
|
|
}
|