<?php

/**
 * setup_database() - instantiate db connection
 */
function setup_database() {

	global $db;

    if (isset($db))
        unset($db);

 	$db = new db('fusion');
}


/**
 *
 */
function get_options() {

	global $options;
	global $db;

	$db->query('SELECT * FROM options');
	$db->exec();

	$rows = $db->fetch_rows();
	foreach ($rows as $row) {
		$options[$row['name']] = $row['value'];
	}
}


/**
 *
 */
function get_user_attributes() {

	global $user_attributes;
	global $db;

	$user_id = null;

	if (isset($_SESSION['user_id']))
		$user_id = $_SESSION['user_id'];

	if (!is_numeric($user_id))
		return null;

	$db->query('SELECT * FROM users WHERE user_id = :user_id LIMIT 1');
	$db->bind(':user_id', $user_id, PDO::PARAM_INT);
	$db->exec();

	$rows = $db->fetch_rows();
	foreach ($rows as $row) {
		foreach ($row as $key => $val) {
			$user_attributes[$key] = $val;
		}
	}
}


/**
 *
 */
function get_option($name, $default = null) {

	global $options;

	if (isset($options[$name]) && !defined('SUBSYSTEM')) {

		return $options[$name];

	} else {

		global $db;

		$db->query('SELECT value FROM options WHERE name = :name LIMIT 1');
 		$db->bind(':name', $name);
		$db->exec();

		$rows = $db->fetch_rows();
		if (count($rows) == 1) {

			$value = $rows[0]['value'];
			$options[$name] = $value;
			return $value;
		}
	}

	return $default;
}




/**
 *
 */
function set_option($name, $value) {

	global $options;
	global $db;

	if (get_option($name) !== null) {
		$db->query('UPDATE options SET value = :value WHERE name = :name');
	} else {
		$db->query('INSERT INTO options (name, value) VALUES (:name, :value)');
	}

	$db->bind(':name', $name);
	$db->bind(':value', $value);
	$db->exec();

	$options[$name] = $value;
}


/**
 *
 */
function delete_option($name) {

	global $options;
	global $db;

	unset($options[$name]);

	$db->query('DELETE FROM options WHERE name = :name LIMIT 1');
	$db->bind(':name', $name);
	$db->exec();
}


/**
 *
 */
function get_array_option($name, $default = array()) {
	
    return unpack_array(get_option($name, $default));
}


/**
 *
 */
function set_array_option($name, $array) {

    return set_option($name, pack_array($array));
}


/**
 * get_meta() - return a keyvalue from a row determined by the other arguments
 * @param int $metatype_id - the metatype id of the row to select
 * @param int $metaobj_id - the metaobj_id of the row to select
 * @param string $keyname - the keyname of the row to select
 */
function get_meta($metatype_id, $metaobj_id, $keyname) {

    global $db;

    $db->query('SELECT * FROM meta WHERE metatype_id = :metatype_id AND metaobj_id = :metaobj_id AND keyname = :keyname LIMIT 1');
    $db->bind(':metatype_id', $metatype_id);
    $db->bind(':metaobj_id', $metaobj_id);
    $db->bind(':keyname', $keyname);
    $db->exec();

    $rows = $db->fetch_rows();
    if (count($rows) == 1) {
    	foreach ($rows as $row) {
    		return $row[0]['keyvalue'];
    	}
    }

    return null;
}


/**
 * set_meta() - set the keyvalue of a meta row determined by the other arguments
 * @param int $metatype_id - the metatype id of the row to update/insert
 * @param int $metaobj_id - the metaobj_id of the row to update/insert
 * @param string $keyname - the keyname of the row to update/insert
 * @param string $keyvalue - the keyvalue of the row to update/insert
 */
function set_meta($metatype_id, $metaobj_id, $keyname, $keyvalue) {

	global $db;

	if (get_meta($metatype_id, $metaobj_id, $keyname) !== null) {

		$id = $rows[0]['id'];
		$db->query('UPDATE meta SET keyvalue = :keyvalue WHERE metatype_id = :metatype_id AND metaobj_id = :metaobj_id AND keyname = :keyname LIMIT 1');

	} else {

		$db->query('INSERT INTO meta (metatype_id, metaobj_id, keyname, keyvalue) VALUES (:metatype_id, :metaobj_id, :keyname, :keyvalue)');
	}

    $db->bind(':metatype_id', $metatype_id);
    $db->bind(':metaobj_id', $metaobj_id);
    $db->bind(':keyname', $keyname);
    $db->bind(':keyvalue', $keyvalue);
    $db->exec();
}



/**
 * delete_meta() - delete a specific meta row determined by the arguments
 * @param int $metatype_id - the metatype id of the row to delete
 * @param int $metaobj_id - the metaobj_id of the row to delete
 * @param string $keyname - the keyname of the row to delete
 */
function delete_meta($metatype_id, $metaobj_id, $keyname) {

    global $db;

	$db->query('DELETE FROM meta WHERE metatype_id = :metatype_id AND metaobj_id = :metaobj_id AND keyname = :keyname LIMIT 1');
    $db->bind(':metatype_id', $metatype_id);
    $db->bind(':metaobj_id', $metaobj_id);
    $db->bind(':keyname', $keyname);
	$db->exec();
}

function is_valid_table($table) {

	global $db;

    $table_rows = $db->exec_query('SHOW tables');

    if ($table_rows !== false && count($table_rows) > 0) {
        foreach ($table_rows as $table_row) {
            foreach ($table_row as $index => $table_val) {
                if ($table === $table_val) {
                	return true;
                }
            }
        }
    }

	return false;
}


function is_valid_column_of_table($potential_column, $table) {

	global $db;

	if (!is_string($potential_column))
		return false;

	if (!is_valid_table($table))
		return false;

	$column_rows = $db->exec_query('DESCRIBE ' . $table);
    if ($column_rows !== false && count($column_rows) > 0) {
        foreach ($column_rows as $column_row) {
            if (!empty($column_row['Field'])) {
                if ($column_row['Field'] === $potential_column) {
                    return true;
                }
            }
        }
    }

	return false;
}

/**
 * is_valid_column_of_query() - attempt to determine if a column [fieldname] can exist given a specific query
 * NOTICE:
 * this is a rather basic implementation, and is used to hopefully prevent SQL injection
 * @param
 * @param
 * @return bool true if the potential column is found via a result set from query
 */
function is_valid_column_of_query($potential_column, $query) {

	global $db;

	if (!is_string($potential_column))
		return false;

	// we need to do some magic to the query incase a bind (paramter) was set initially
	// we get rid of [where something = something]
	$test_query = trim(strtoupper($query));

	// if it isn't a select query then bail out
	if (substr($test_query, 0, 6) != 'SELECT')
		return false;

	if (strpos($test_query, "WHERE") !== false) {

		// convert all whitespace to a single space
		preg_replace("/\s+/", " ", $test_query);
		$where_pos = strpos($test_query, " WHERE ");
		if ($where_pos !== false) {

			$query = substr($query, 0, $where_pos);
		}
	}

	$db->query($query);
	$db->exec();
	$rows = $db->fetch_rows();
	
	if (isset($rows[0][$potential_column]))
		return true;

	return false;
}

// Grab the version of specified server from the DB
function get_version($server_id, $trim=true) {

	global $db;

	$bind_array = array(':server_id' => $server_id);
	$rows = $db->exec_query('SELECT version FROM servers WHERE server_id = :server_id LIMIT 1', $bind_array);

	$version = $rows[0]['version'];

	// Check to see if DEV/REV
	if (strpos($version, '.') !== false && $trim) {
		$i = explode('.', $version);
		$version = "{$i[0]}.{$i[1]}.{$i[2]}";
	}

	return $version;
}