Files
api/services/nginx/app/objects/motorapi_lookups_o.php
T
Jeppe Bundgaard 7a852f5b54 Add nullable return types and improve exception handling in MotorAPI
- Updated `getCachedResult` methods across `motorapi`, `motorapi_i`, and `motorapi_lookups_o` to return `?object` for nullable results.
- Enhanced error handling in `xlvask_parser_stor_bil` by wrapping `getLicensePlateInformation` in a try-catch block to handle API exceptions gracefully.
- Introduced `cleanJSON` method in `motorapi` to sanitize and validate JSON data, ensuring robust parsing of cached responses.
- Optimized `getCachedResult` logic to handle null and invalid JSON scenarios with detailed error reporting.
2025-08-31 13:33:10 +02:00

176 lines
5.6 KiB
PHP

<?php
namespace objects;
use classes\db;
use classes\object_property;
use Exception;
use traits\db_object_t;
class motorapi_lookups_o extends db
{
use db_object_t;
public object_property $license_plate;
public object_property $result;
public object_property $endpoint;
public object_property $created_at;
public function structure(): void
{
$this->setTable('motorapi_lookups');
}
/**
* Add a motorapi lookup
* @param string $license_plate
* @param string $result
* @param string $endpoint
* @return void
* @throws Exception If the object was not created successfully
*/
public function add(string $license_plate, string $result, string $endpoint): void
{
global /** @var db $db */
$db;
// Sanitize the input
$license_plate = $db->escape_string($license_plate);
$result = $db->escape_string($result);
$endpoint = $db->escape_string($endpoint);
// Add the object
$tmp_id = self::add_object([
'license_plate' => $license_plate,
'result' => $result,
'endpoint' => $endpoint
]);
$this->id = $tmp_id;
self::getObjectProperties();
self::objectChanged();
}
public function getObjectProperties(): void
{
$this->license_plate = new object_property($this->table, $this->id, 'license_plate', 'string', false);
$this->result = new object_property($this->table, $this->id, 'result', 'string', false);
$this->endpoint = new object_property($this->table, $this->id, 'endpoint', 'string', false);
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'datetime', false);
}
public function objectChanged(): void
{
//TODO: Add cache invalidation
}
/**
* Get the amount of motorapi lookups created today
* @return int
*/
public function getTodayCount(): int
{
global /** @var db $db */
$db;
$sql = 'SELECT COUNT(*) FROM ' . $this->table . ' WHERE DATE(created_at) = CURDATE()';
$result = $db->query($sql);
return (int)$result->fetch_row()[0];
}
public function asArray(): array
{
return [
'id' => (int)$this->id,
'license_plate' => (string)$this->license_plate->value(),
'result' => (string)$this->result->value(),
'endpoint' => (string)$this->endpoint->value(),
'created_at' => (string)$this->created_at->value(),
];
}
/**
* Is the license plate in the cache?
* @param string $license_plate
* @return bool
* @throws Exception If the license plate is not valid
*/
public function isCached(string $license_plate): bool
{
global /** @var db $db */
$db;
if (!self::validateLicensePlateFormat($license_plate)) {
throw new Exception('The license plate is not valid.');
}
$result = self::getFieldsWhere(['license_plate' => $license_plate], ['id']);
return !empty($result);
}
/**
* Validate the format of a license plate
* @note This simply checks if the license plate is in the format of two letters followed by four or five numbers.
* @note This does not check if the license plate is actually valid.
* @param string $license_plate
* @return bool
*/
public static function validateLicensePlateFormat(string $license_plate): bool
{
return (bool)preg_match('/^[A-Z]{2}[0-9]{4,5}$/', $license_plate);
}
/**
* Get the (latest) cached result for a license plate
* @param string $license_plate
* @return object|null The motorapi_lookups_o object or null if not found
* @throws Exception If the license plate is not valid or the response is not cached
*/
public function getCachedResult(string $license_plate): ?object
{
global /** @var db $db */
$db;
if (!self::validateLicensePlateFormat($license_plate)) {
throw new Exception('The license plate is not valid.');
}
$result = self::getFieldsWhere(['license_plate' => $license_plate], ['id', 'result', 'endpoint', 'created_at']);
if (!$result) {
return null;
}
// Get the latest result
$latest = array_pop($result);
$this->id = $latest['id'];
self::getObjectProperties();
return $this;
}
/**
* Get all cached results with the "result" field containing a specific substring(s)
* @param string|array $substrings
* @return array An array of motorapi_lookups_o objects
* @throws Exception If no results are found
*/
public function getCachedResultsBySubstring(string|array $substrings): array
{
global /** @var db $db */
$db;
if (is_string($substrings)) {
$substrings = [$substrings];
}
$where_clauses = [];
foreach ($substrings as $substring) {
$escaped_substring = $db->escape_string($substring);
$where_clauses[] = "result LIKE '%$escaped_substring%'";
}
$where_sql = implode(' OR ', $where_clauses);
$sql = "SELECT id FROM " . $this->table . " WHERE $where_sql";
$result = $db->query($sql);
if ($result->num_rows === 0) {
throw new Exception('No results found.');
}
$objects = [];
while ($row = $result->fetch_assoc()) {
$obj = new self();
$obj->id = $row['id'];
$obj->getObjectProperties();
$objects[] = $obj;
}
return $objects;
}
}