summaryrefslogtreecommitdiffstats
path: root/inc/property.inc.php
diff options
context:
space:
mode:
Diffstat (limited to 'inc/property.inc.php')
-rw-r--r--inc/property.inc.php159
1 files changed, 104 insertions, 55 deletions
diff --git a/inc/property.inc.php b/inc/property.inc.php
index 3911b0d4..aaf03254 100644
--- a/inc/property.inc.php
+++ b/inc/property.inc.php
@@ -1,5 +1,7 @@
<?php
+declare(strict_types=1);
+
/**
* Get or set simple key-value-pairs, backed by the database
* to make them persistent.
@@ -16,12 +18,13 @@ class Property
* @param mixed $default value to return if $key does not exist in the property store
* @return mixed the value attached to $key, or $default if $key does not exist
*/
- public static function get($key, $default = false)
+ public static function get(string $key, $default = false)
{
if (self::$cache === false) {
+ self::$cache = [];
$NOW = time();
$res = Database::simpleQuery("SELECT name, dateline, value FROM property");
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
if ($row['dateline'] != 0 && $row['dateline'] < $NOW)
continue;
self::$cache[$row['name']] = $row['value'];
@@ -33,24 +36,30 @@ class Property
}
/**
- * Set value in property store.
+ * Set value in property store. Passing null or false as the value deletes the
+ * entry from the property table.
*
* @param string $key key of value to set
- * @param string $value the value to store for $key
+ * @param string|null|false $value the value to store for $key
* @param int $maxAgeMinutes how long to keep this entry around at least, in minutes. 0 for infinite
*/
- public static function set($key, $value, $maxAgeMinutes = 0)
+ public static function set(string $key, $value, int $maxAgeMinutes = 0): void
{
- if (self::$cache === false || self::get($key) != $value) { // Simple compare, so it works for numbers accidentally casted to string somewhere
+ if ($value === false || $value === null) {
+ Database::exec("DELETE FROM property WHERE name = :key", ['key' => $key]);
+ if (self::$cache !== false) {
+ unset(self::$cache[$key]);
+ }
+ } else {
Database::exec("INSERT INTO property (name, value, dateline) VALUES (:key, :value, :dateline)"
- . " ON DUPLICATE KEY UPDATE value = VALUES(value), dateline = VALUES(dateline)", array(
+ . " ON DUPLICATE KEY UPDATE value = VALUES(value), dateline = VALUES(dateline)", [
'key' => $key,
'value' => $value,
'dateline' => ($maxAgeMinutes === 0 ? 0 : time() + ($maxAgeMinutes * 60))
- ));
- }
- if (self::$cache !== false) {
- self::$cache[$key] = $value;
+ ]);
+ if (self::$cache !== false) {
+ self::$cache[$key] = $value;
+ }
}
}
@@ -60,33 +69,76 @@ class Property
* @param string $key Key of list to get all items for
* @return array All the items matching the key
*/
- public static function getList($key)
+ public static function getList(string $key): array
{
- $res = Database::simpleQuery("SELECT dateline, value FROM property_list WHERE name = :key", compact('key'));
+ $res = Database::simpleQuery("SELECT subkey, dateline, value FROM property_list
+ WHERE `name` = :key", compact('key'));
$NOW = time();
- $return = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $return = [];
+ foreach ($res as $row) {
if ($row['dateline'] != 0 && $row['dateline'] < $NOW)
continue;
- $return[] = $row['value'];
+ $return[$row['subkey']] = $row['value'];
}
return $return;
}
/**
+ * @return ?string entry from property list
+ */
+ public static function getListEntry(string $key, int $subkey): ?string
+ {
+ $row = Database::queryFirst("SELECT dateline, `value` FROM property_list
+ WHERE `name` = :key AND subkey = :subkey", ['key' => $key, 'subkey' => $subkey]);
+ if ($row === false || ($row['dateline'] != 0 && $row['dateline'] < time()))
+ return null;
+ return $row['value'];
+ }
+
+ /**
* Add item to property list.
*
* @param string $key key of value to set
* @param string $value the value to add for $key
* @param int $maxAgeMinutes how long to keep this entry around at least, in minutes. 0 for infinite
+ * @return int The auto generated sub-key
*/
- public static function addToList($key, $value, $maxAgeMinutes = 0)
+ public static function addToList(string $key, string $value, int $maxAgeMinutes = 0): int
{
Database::exec("INSERT INTO property_list (name, value, dateline) VALUES (:key, :value, :dateline)", array(
'key' => $key,
'value' => $value,
'dateline' => ($maxAgeMinutes === 0 ? 0 : time() + ($maxAgeMinutes * 60))
));
+ return Database::lastInsertId();
+ }
+
+ /**
+ * Update existing entry in property list.
+ *
+ * @param string $key key of list
+ * @param int $subkey subkey of entry in list
+ * @param string $value new value to set entry to
+ * @param int $maxAgeMinutes the new lifetime of that entry
+ * @param ?string $expectedValue if not null, the value will only be updated if it currently has this value
+ * @return bool whether the entry existed and has been updated
+ */
+ public static function updateListEntry(string $key, int $subkey, string $value,
+ int $maxAgeMinutes = 0, string $expectedValue = null): bool
+ {
+ $args = [
+ 'name' => $key,
+ 'subkey' => $subkey,
+ 'newvalue' => $value,
+ 'dateline' => ($maxAgeMinutes === 0 ? 0 : time() + ($maxAgeMinutes * 60)),
+ ];
+ if ($expectedValue !== null) {
+ $args['oldvalue'] = $expectedValue;
+ return Database::exec("UPDATE property_list SET `value` = :newvalue, dateline = :dateline
+ WHERE `name` = :name AND subkey = :subkey AND `value` = :oldvalue", $args) > 0;
+ }
+ return Database::exec("UPDATE property_list SET `value` = :newvalue, dateline = :dateline
+ WHERE `name` = :name AND subkey = :subkey", $args) > 0;
}
/**
@@ -97,7 +149,7 @@ class Property
* @param string $value item to remove
* @return int number of items removed
*/
- public static function removeFromList($key, $value)
+ public static function removeFromListByVal(string $key, string $value): int
{
return Database::exec("DELETE FROM property_list WHERE name = :key AND value = :value", array(
'key' => $key,
@@ -106,12 +158,28 @@ class Property
}
/**
+ * Remove given item from property list. If the list contains this item
+ * multiple times, they will all be removed.
+ *
+ * @param string $key Key of list
+ * @param int $value item to remove
+ * @return bool whether item was found and removed
+ */
+ public static function removeFromListByKey(string $key, int $subkey): bool
+ {
+ return Database::exec("DELETE FROM property_list WHERE name = :key AND subkey = :subkey", array(
+ 'key' => $key,
+ 'subkey' => $subkey,
+ )) > 0;
+ }
+
+ /**
* Delete entire list with given key.
*
* @param string $key Key of list
* @return int number of items removed
*/
- public static function clearList($key)
+ public static function clearList(string $key): int
{
return Database::exec("DELETE FROM property_list WHERE name = :key", compact('key'));
}
@@ -120,12 +188,12 @@ class Property
* Legacy getters/setters
*/
- public static function getServerIp()
+ public static function getServerIp(): string
{
- return self::get('server-ip', 'none');
+ return self::get('server-ip', 'invalid');
}
- public static function setServerIp($value, $automatic = false)
+ public static function setServerIp(string $value, bool $automatic = false): bool
{
if ($value === self::getServerIp())
return false;
@@ -135,19 +203,15 @@ class Property
return true;
}
- public static function getBootMenu()
- {
- return json_decode(self::get('ipxe-menu'), true);
- }
-
- public static function setBootMenu($value)
- {
- self::set('ipxe-menu', json_encode($value));
- }
-
- public static function getVmStoreConfig()
+ public static function getVmStoreConfig(): array
{
- return json_decode(self::get('vmstore-config'), true);
+ $data = self::get('vmstore-config');
+ if (!is_string($data))
+ return [];
+ $data = json_decode($data, true);
+ if (!is_array($data))
+ return [];
+ return $data;
}
public static function getVmStoreUrl()
@@ -169,21 +233,6 @@ class Property
self::set('vmstore-config', json_encode($value));
}
- public static function getDownloadTask($name)
- {
- return self::get('dl-' . $name);
- }
-
- public static function setDownloadTask($name, $taskId)
- {
- self::set('dl-' . $name, $taskId, 5);
- }
-
- public static function getCurrentSchemaVersion()
- {
- return self::get('webif-version');
- }
-
public static function setLastWarningId($id)
{
self::set('last-warn-event-id', $id);
@@ -194,22 +243,22 @@ class Property
return self::get('last-warn-event-id', 0);
}
- public static function setNeedsSetup($value)
+ public static function setNeedsSetup(bool $value)
{
- self::set('needs-setup', $value);
+ self::set('needs-setup', (int)$value);
}
- public static function getNeedsSetup()
+ public static function getNeedsSetup(): bool
{
- return self::get('needs-setup');
+ return self::get('needs-setup') != 0;
}
- public static function setPasswordFieldType($value)
+ public static function setPasswordFieldType(string $value)
{
self::set('password-type', $value);
}
- public static function getPasswordFieldType()
+ public static function getPasswordFieldType(): string
{
return self::get('password-type', 'password');
}