summaryrefslogblamecommitdiffstats
path: root/inc/property.inc.php
blob: aaf03254ca3d6eca2ac4988af67eb76928f3b2aa (plain) (tree)
1
2
3
4
5
6
7
8
9
10

     

                        





                                                            
 
                                      
 






                                                                                             
                                                                 

                                             
                                          

                                                                                                   
                                                

                                                                                     


                                                                           

                                               

                                          
 
           

                                                                                      

                                                 
                                                                      
                                                                                                            
           
                                                                                     
         





                                                                                                  
                                                                                                                      
                                                                                                                  

                                                  
                                                                                                         



                                                            

                 
 





                                                              
                                                          
         

                                                                                               
                              
                             
                                        

                                                                             
                                                                




                               

                                                   
                                                                              








                                                                                                         




                                                                                                            
                                                 
           
                                                                                                 





                                                                                                                           








                                                         
                                                                   
                                                                                                                   

                                                                      

                                                                                                                                                                           









                                                                                                                 
                                                                                                               

                                                                                                         
                                                                                       









                                                                               
                                                                                   






                                                                                                              
           















                                                                                                                




                                              
                                                          



                                                                                                     



                                 
                                                    
         
                                                         
         
 
                                                                                        
         

                                                   
                                                                                                                                           
                                               
                                         
                            
         
 
                                                        
         






                                                    
         
 












                                                       
 



                                                                 
 








                                                          
 
                                                         
         
                                                      
         
 
                                                    
         
                                                     
         
        
                                                                  
         
                                                   

         
                                                             


                                                              
 
 
<?php

declare(strict_types=1);

/**
 * Get or set simple key-value-pairs, backed by the database
 * to make them persistent.
 */
class Property
{

	private static $cache = false;

	/**
	 * Retrieve value from property store.
	 *
	 * @param string $key key to retrieve the value of
	 * @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(string $key, $default = false)
	{
		if (self::$cache === false) {
			self::$cache = [];
			$NOW = time();
			$res = Database::simpleQuery("SELECT name, dateline, value FROM property");
			foreach ($res as $row) {
				if ($row['dateline'] != 0 && $row['dateline'] < $NOW)
					continue;
				self::$cache[$row['name']] = $row['value'];
			}
		}
		if (!isset(self::$cache[$key]))
			return $default;
		return self::$cache[$key];
	}

	/**
	 * 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|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(string $key, $value, int $maxAgeMinutes = 0): void
	{
		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)", [
				'key' => $key,
				'value' => $value,
				'dateline' => ($maxAgeMinutes === 0 ? 0 : time() + ($maxAgeMinutes * 60))
			]);
			if (self::$cache !== false) {
				self::$cache[$key] = $value;
			}
		}
	}

	/**
	 * Retrieve property list from the store.
	 *
	 * @param string $key Key of list to get all items for
	 * @return array All the items matching the key
	 */
	public static function getList(string $key): array
	{
		$res = Database::simpleQuery("SELECT subkey, dateline, value FROM property_list
			WHERE `name` = :key", compact('key'));
		$NOW = time();
		$return = [];
		foreach ($res as $row) {
			if ($row['dateline'] != 0 && $row['dateline'] < $NOW)
				continue;
			$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(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;
	}

	/**
	 * 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 string $value item to remove
	 * @return int number of items removed
	 */
	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,
			'value' => $value,
		));
	}

	/**
	 * 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(string $key): int
	{
		return Database::exec("DELETE FROM property_list WHERE name = :key", compact('key'));
	}

	/*
	 * Legacy getters/setters
	 */

	public static function getServerIp(): string
	{
		return self::get('server-ip', 'invalid');
	}

	public static function setServerIp(string $value, bool $automatic = false): bool
	{
		if ($value === self::getServerIp())
			return false;
		EventLog::info('Server IP changed from ' . self::getServerIp() . ' to ' . $value . ($automatic ? ' (auto detected)' : ''));
		self::set('server-ip', $value);
		Event::serverIpChanged();
		return true;
	}

	public static function getVmStoreConfig(): array
	{
		$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()
	{
		$store = self::getVmStoreConfig();
		if (!isset($store['storetype']))
			return false;
		if ($store['storetype'] === 'nfs')
			return $store['nfsaddr'];
		if ($store['storetype'] === 'cifs')
			return $store['cifsaddr'];
		if ($store['storetype'] === 'internal')
			return '<local>';
		return '<unknown>';
	}

	public static function setVmStoreConfig($value)
	{
		self::set('vmstore-config', json_encode($value));
	}

	public static function setLastWarningId($id)
	{
		self::set('last-warn-event-id', $id);
	}

	public static function getLastWarningId()
	{
		return self::get('last-warn-event-id', 0);
	}

	public static function setNeedsSetup(bool $value)
	{
		self::set('needs-setup', (int)$value);
	}

	public static function getNeedsSetup(): bool
	{
		return self::get('needs-setup') != 0;
	}
	
	public static function setPasswordFieldType(string $value)
	{
		self::set('password-type', $value);
	}
	
	public static function getPasswordFieldType(): string
	{
		return self::get('password-type', 'password');
	}

}