';
switch ($e->getCode()) {
case 2002:
echo "Unable to connect to database, perhaps host info is wrong.\n";
break;
case 1044:
case 1045:
case 1698:
// access denied to db or generic access denied
echo "Unable to connect to database, perhaps username or password is wrong.\n";
break;
case 1049:
echo "Unable to connect to database, perhaps database name is wrong.\n";
break;
default:
print_r($e);
}
echo '
';
echo '';
exit(1);
}
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
# $pdo->query("SET lc_time_names='de_DE'");
try {
$sth = $pdo->query("SELECT valint FROM settings WHERE userid=0 AND sno=0");
} catch (PDOException $e) {
if ($e->getCode() == 1146) {
echo '
';
echo 'Settings table not found! Perhaps database is not initialized';
echo '
';
exit(1);
}
}
$g_db_scheme_version = $sth->fetchColumn();
// TODO Check version
$user = User::GetInstance(); // There can be only one
if ($g_scriptname != 'login.php') {
$user->init_from_session();
$user->load_vessel();
$user->load_settings();
}
$action = NULL;
$valid = FALSE;
// document storage
$g_doc_mimetypes = ['image/png', 'image/jpeg', 'image/svg+xml', 'application/pdf'];
// form option lists
$g_opt_all = array(-2 => _('― all ―'));
$g_opt_none = array(-1 => _('― none ―'));
$g_opt_empty = array('' => _('― none ―'));
$g_opt_unknown = array(-1 => _('― unknown ―'));
// Initialize message system
$g_message = new Message;
$g_success = new MessageSuccess;
$g_warning = new MessageWarning;
$g_error = new MessageError;
// ========== MESSAGE FUNCTIONS ===============================================
class Message {
var $count = 0;
var $text = array();
var $caption;
var $alertclass;
function __construct() {
$this->caption = _('Information');
$this->alertclass = 'alert-info';
if (isset($_SESSION['message']['info'])) {
$this->Add($_SESSION['message']['info']);
unset($_SESSION['message']['info']);
}
}
function SetCaption($str) {
$this->caption = $str;
}
function Add($msg) {
$this->count++;
$this->text[$this->count] = $msg;
}
function GetCount() {
return $this->count;
}
function PrintOut() {
if ($this->count > 0) {
echo '
', "\n";
echo '
', $this->caption, "
\n";
echo "
\n";
for ($i=1; $i<=$this->count; $i++) {
echo "\t
", $this->text[$i],"
\n";
}
echo "
\n";
echo '', "\n";
echo "
\n";
}
}
}
class MessageSuccess extends Message {
function __construct() {
$this->caption = _('Success');
$this->alertclass = 'alert-success';
if (isset($_SESSION['message']['succ'])) {
$this->Add($_SESSION['message']['succ']);
unset($_SESSION['message']['succ']);
}
}
}
class MessageWarning extends Message {
function __construct() {
$this->caption = _('Warning');
$this->alertclass = 'alert-warning';
if (isset($_SESSION['message']['warn'])) {
$this->Add($_SESSION['message']['warn']);
unset($_SESSION['message']['warn']);
}
}
}
class MessageError extends Message {
function __construct() {
$this->caption = _('Error');
$this->alertclass = 'alert-danger';
if (isset($_SESSION['message']['err'])) {
$this->Add($_SESSION['message']['err']);
unset($_SESSION['message']['err']);
}
}
}
// ========== USER FUNCTIONS ==================================================
class User {
private static $instance = NULL;
private $loggedin;
private $errormessage;
public $id;
public $login;
public $displayname;
public $role;
public $flags;
public $vid; // current selected vessel
public $vessel; // name of current vessel
public $datefmt;
public $rows_pp;
public $menu;
private function __construct() {
global $g_rows_pp;
$this->loggedin = FALSE;
$this->errormessage = NULL;
$this->flags = [];
$this->vid = 1;
$this->vessel = 'Yacht';
$this->datefmt = 'Y-m-d';
$this->rows_pp = $g_rows_pp;
$this->menu = [1, 2, 3, 4, 5, 6];
}
public static function getInstance() {
if (self::$instance == NULL) {
self::$instance = new User();
}
return self::$instance;
}
function login($user_name, $user_pass) {
global $pdo;
if ($user_name == '' or $user_pass == '') {
$this->loggedin = FALSE;
$this->errormessage = _('Username or password was empty');
return FALSE;
}
$sql = "SELECT userid, pass, displayname, role, flags FROM user WHERE login=?";
$sth = $pdo->prepare($sql);
$sth->execute([$user_name]);
$row = $sth->fetch(PDO::FETCH_OBJ);
$this->role = $row->role;
$this->flags = array_filter(explode(',', $row->flags));
if (($row->flags != 0) and ($row->flags != '')) {
// deleted or locked, intentionally not return detailed reason
$this->errormessage = _('User account does not exist');
} elseif (password_verify($user_pass, $row->pass)) {
// password check successful
$_SESSION['userid'] = $row->userid;
$this->loggedin = TRUE;
$target = $_SESSION['prelogin'] ?? 'index.php';
unset($_SESSION['prelogin']);
header_location($target);
} else {
$this->errormessage = _('Username or password invalid');
}
return FALSE;
}
function logout() {
global $pdo;
// remove session completely
$_SESSION = array();
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
session_destroy();
}
function init_from_session() {
global $pdo;
if (!isset($_SESSION['userid'])) {
$this->loggedin = FALSE;
$this->errormessage = _('User not logged in');
$this->id = NULL;
return;
}
$this->id = $_SESSION['userid'];
$sql = "SELECT displayname, role FROM user WHERE userid=?";
$sth = $pdo->prepare($sql);
$sth->execute([$this->id]);
$row = $sth->fetch();
if ($row) {
$this->displayname = $row['displayname'];
$this->role = $row['role'];
}
}
function load_vessel() {
global $pdo;
$sql = "SELECT v.vid, v.vesselname "
. "FROM settings AS s INNER JOIN vessel AS v ON s.valint=v.vid "
. "WHERE s.userid=? and s.sno=1";
$sth = $pdo->prepare($sql);
$sth->execute([$this->id]);
$row = $sth->fetch();
if ($row) {
$this->vid = $row['vid'];
$this->vessel = $row['vesselname'];
}
}
function load_settings() {
global $pdo;
// additional user settings
// date format from user settings
$sql = "SELECT valstr FROM settings WHERE userid=? AND sno=2";
$sth = $pdo->prepare($sql);
$sth->execute([$this->id]);
$user_datefmt = $sth->fetchColumn();
if ($user_datefmt) {
$this->datefmt = $user_datefmt;
}
// pagination rows from user settings
$sql = "SELECT valint FROM settings WHERE userid=? AND sno=10";
$sth = $pdo->prepare($sql);
$sth->execute([$this->id]);
$user_rows_pp = $sth->fetchColumn();
if ($user_rows_pp) {
$this->rows_pp = $user_rows_pp;
}
// user defined menu
$sql = "SELECT valstr FROM settings WHERE userid=? AND sno=3";
$sth = $pdo->prepare($sql);
$sth->execute([$this->id]);
$res = $sth->fetchColumn();
if ($res === false) {
$sql = "INSERT INTO settings (userid, sno, valstr) VALUES (?, 3, ?)";
$sth = $pdo->prepare($sql);
$sth->execute([$this->id, implode(',', $this->menu)]);
} else {
$this->menu = array_map('intval', explode(',', $res));
}
}
function get_last_error() {
return $this->errormessage;
}
}
function get_userlist() {
// Get list of all users for fast name lookup
global $pdo;
$ulist = array(-1 => ['-', 0]); // unknown
$sql = "SELECT userid, displayname, role, flags FROM user ORDER BY displayname";
$sth = $pdo->query($sql);
$res = $sth->fetchAll();
foreach ($res as $row) {
$flags = array_filter(explode(',', $row['flags']));
$deleted = in_array('deleted', $flags);
$locked = in_array('locked', $flags);
$ulist[$row['userid']] = [$row['displayname'], $deleted, $locked];
}
return $ulist;
}
// ========== DATABASE FUNCTIONS ==============================================
function db_exec_insert($table, $params) {
// $params must have keys corresponding to table fields prefixed with ':'
// e.g. $param[':field']
global $pdo;
global $g_error;
$keys = array_keys($params);
$fields = join(', ', array_map(function($s) { return ltrim($s, ':'); }, $keys));
$pnames = join(', ', $keys);
$sql = "INSERT INTO $table ($fields) VALUES ($pnames)";
// $sth = $pdo->prepare("INSERT INTO $table ($fields) VALUES ($pnames)");
$sth = $pdo->prepare($sql);
try {
$sth->execute($params);
} catch (PDOexception $e) {
$g_error->Add('SQL-Error: '. $e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($params, true));
return false;
}
return $pdo->LastInsertId();
}
function db_exec_update($table, $params, $pk) {
// primary key can be a single field name or multiple fields: $pk is an array
global $pdo;
global $g_error;
// remove primary key fields from list of fields to update
if (is_array($pk)) {
if (count($pk) == 1) {
$pk = $pk[0];
$fields = $params;
unset($fields[':'.$pk]);
$where = "$pk=:$pk";
} else {
$pkparams = array_map(fn($value) => ':' . $value, $pk);
$fields = array_diff_key($params, array_flip($pkparams));
$where = join(' AND ', array_map(fn($s) => "$s=:$s", $pk));
}
} else {
$fields = $params;
unset($fields[':'.$pk]);
$where = "$pk=:$pk";
}
$fieldlist = join(', ', array_map(fn($s) => ltrim($s, ':') . '=' . $s, array_keys($fields)));
$sql = "UPDATE $table SET $fieldlist WHERE $where";
$sth = $pdo->prepare($sql);
try {
$sth->execute($params);
} catch (PDOexception $e) {
$g_error->Add('SQL-Error: '. $e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($params, true));
return false;
}
return true;
}
function db_exec_delete($table, $condition, $params) {
// WIP untested!
// condition contains the where part of the sql statement
// params are values for placeholders in condition
// returns the number of deleted records
global $pdo;
global $g_error;
// convert params to array if single value is given
if (!is_array($params)) {
$params = [$params];
}
$sql = "DELETE FROM $table";
if (!empty($condition)) {
$sql .= ' WHERE ' . $condition;
}
$sth = $pdo->prepare($sql);
try {
$sth->execute($params);
} catch (PDOexception $e) {
$g_error->Add('SQL-Error: '. $e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($params, true));
return -1;
}
return $sth->rowCount();
}
function db_clear_filter($sno) {
global $user;
global $pdo;
$sql = "DELETE FROM settings WHERE userid=? AND sno=?";
$sth = $pdo->prepare($sql);
try {
$sth->execute([$user->id, $sno]);
} catch (PDOexception $e) {
$g_warning->Add('SQL-Error: '. $e->getMessage());
$g_warning->Add($sql);
$g_warning->Add('Setting: ', $sno);
return false;
}
return true;
}
function db_save_filter($flt, $sno) {
global $user;
global $pdo;
global $g_warning;
$sql = "UPDATE settings SET valstr=? WHERE userid=? AND sno=?";
$sth = $pdo->prepare($sql);
try {
$sth->execute([json_encode($flt), $user->id, $sno]);
} catch (PDOexception $e) {
$g_warning->Add('SQL-Error: '. $e->getMessage());
$g_warning->Add($sql);
$g_warning->Add(print_r($flt, true));
$g_warning->Add('Setting: ', $sno);
return false;
}
return true;
}
function get_enum($enum) {
// translate and beautify enums
$lookup = array(
'NULL' => _('n/a'),
'active' => _('Active'),
'bad' => _('Bad'),
'box' => _('Box'),
'cable' => _('Cable'),
'cat' => _('Catamaran'),
'completed' => _('Completed'),
'closed' => _('Closed'),
'company' => _('Company'),
'defect' => _('Defect'),
'deleted' => _('Deleted'),
'done' => _('Done'),
'drawing' => _('Drawing'),
'equipment' => _('Equipment'),
'estimated' => _('Estimated'),
'excellent' => _('Excellent'),
'fair' => _('Fair'),
'finished' => _('Finished'),
'fixed' => _('Fixed'),
'fuse' => _('Fuse'),
'generic' => _('Generic'),
'good' => _('Good'),
'high' => _('High'),
'historic' => _('Historic'),
'invoice' => _('Invoice'),
'locked' => _('Locked'),
'low' => _('Low'),
'manual' => _('Manual'),
'medium' => _('Medium'),
'mono' => _('Monohull'),
'new' => _('New'),
'none' => _('None'),
'normal' => _('Normal'),
'ongoing' => _('Ongoing'),
'open' => _('Open'),
'ordered' => _('Ordered'),
'paused' => _('Paused'),
'pending' => _('Pending'),
'picture' => _('Picture'),
'planned' => _('Planned'),
'precise' => _('Precise'),
'project' => _('Project'),
'removed' => _('Removed'),
'repairable' => _('Repairable'),
'rough' => _('Rough'),
'storage' => _('Storage'),
'task' => _('Task'),
'tri' => _('Trimaran'),
'unknown' => _('Unknown'),
'user' => _('User'),
'vessel' => _('Vessel'),
'waiting' => _('waiting')
);
return $lookup[$enum] ?? $enum;
}
function db_load_enum($table, $column, $lookup=false, $as_dict=false, $check_null=false) {
// returns array of enum-values as defined in database
// if lookup is true the name lookup and translaton is applied
// if as_dict is true the enum value is returned as the array key
// if check_null is true the nullable-check is applied and returned
// works also for set datatype
global $pdo;
$sql = "SELECT TRIM(TRAILING ')' FROM SUBSTRING(column_type,6)), is_nullable "
. "FROM information_schema.columns "
. "WHERE table_schema=DATABASE() AND table_name=? AND column_name=?";
$sth = $pdo->prepare($sql);
$sth->execute([$table, $column]);
$row = $sth->fetch(PDO::FETCH_NUM);
// for PHP < 7.4
// return array_map(function($x) { return trim($x, "'"); }, explode(',', $row[0]));
// for PHP => 7.4
$arr = array_map(fn($x) => trim($x, "'"), explode(',', $row[0]));
// prepend special value NULL if column is nullable
if ($check_null and $row[1] == 'YES') {
array_unshift($arr, 'NULL');
}
if ($lookup) {
if ($as_dict) {
$dict = array();
foreach ($arr as $x) {
$dict[$x] = get_enum($x);
}
return $dict;
} else {
return array_map(fn($x) => get_enum($x), $arr);
}
} else {
return $arr;
}
}
function db_load_taglist($objtype, $objid) {
// returns comma separated list for object
global $pdo;
global $g_error;
$taglist = '';
$sql = "SELECT GROUP_CONCAT(tagname) "
. "FROM tagref JOIN tag USING (tagid) "
. "WHERE objtype=? AND objid=?";
$sth = $pdo->prepare($sql);
try {
$sth->execute([$objtype, $objid]);
$taglist = $sth->fetchColumn();
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
}
return $taglist;
}
function db_save_taglist($objtype, $objid, $taglist) {
global $pdo;
global $g_error;
// WIP
// - taglist is comma separated string
// - create not existing tags
// - update tagref: create new, remove unused
$tags = array_filter(explode(',', preg_replace('/\s+/u', '', $taglist)));
if (empty($tags)) {
// remove all from tagref
$sth = $pdo->prepare("DELETE FROM tagref WHERE objtype=? AND objid=?");
try {
$sth->execute([$objtype, $objid]);
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
}
} else {
// get list of non existing tags
$in = str_repeat('?,', count($tags) - 1) . '?';
$sql = "SELECT tagid, tagname FROM tag WHERE tagname IN ($in)";
$sth = $pdo->prepare($sql);
try {
$sth->execute(array_values($tags));
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
}
$tagids = array();
$existing = array();
foreach ($sth->fetchAll() as $row) {
$existing[] = $row['tagname'];
$tagids[] = $row['tagid'];
}
$newtags = array_diff($tags, $existing);
$sth = $pdo->prepare("INSERT INTO tag (tagname) VALUES (?)");
foreach ($newtags as $t) {
// maxlength 20 for each tag!
$sth->execute([substr($t, 0, 20)]);
$tagids[] = $pdo->LastInsertId();
}
// update references
$sql = "SELECT tagid FROM tagref WHERE objtype=? AND objid=?";
$sth = $pdo->prepare($sql);
$sth->execute([$objtype, $objid]);
$refids = array();
$obsolete = array();
foreach ($sth->fetchAll() as $row) {
if (in_array($row['tagid'], $tagids)) {
// mark existing used references
$refids[] = $row['tagid'];
} else {
// obsolete reference
$obsolete[] = $row['tagid'];
}
}
// create missing references
$missing = array_diff($tagids, $refids);
if (! empty($missing)) {
$sql = "INSERT INTO tagref (tagid, objid, objtype) VALUES (?, ?, ?)";
$sth = $pdo->prepare($sql);
foreach ($missing as $m) {
$sth->execute([$m, $objid, $objtype]);
}
}
// remove obsolete references
if (! empty($obsolete)) {
$sql = "DELETE FROM tagref WHERE tagid=? AND objid=? and objtype=?";
$sth = $pdo->prepare($sql);
foreach ($obsolete as $o) {
$sth->execute([$o, $objid, $objtype]);
}
}
}
}
function db_get_tag_target($objtype, $objid) {
// get page name and desctiption e.g. for link creation
global $pdo;
global $g_error;
switch ($objtype) {
case 'equip':
$sql = "SELECT ename FROM equipment WHERE eid=?";
$target = "equipment.php";
break;
case 'inv':
$sql = "SELECT invname FROM inventory WHERE invid=?";
$target = "inventory.php";
break;
case 'prov':
$sql = "SELECT provname FROM provisions WHERE provvid=?";
$target = "provisions.php";
break;
case 'doc':
$sql = "SELECT title FROM document WHERE docid=?";
$target = "documents.php";
break;
case 'proj':
$sql = "SELECT projname FROM project WHERE projid=?";
$target = "projects.php";
break;
case 'task':
$sql = "SELECT taskname FROM task WHERE taskid=?";
$target = "task.php";
break;
case 'maint':
$sql = "SELECT activities FROM maintenance WHERE maintid=?";
$target = 'maintenance.php';
break;
}
$sth = $pdo->prepare($sql);
$sth->execute([$objid]);
$desc = $sth->fetchColumn();
return [$target, $desc];
}
function db_get_ddtext($ddid, $ddval) {
// returns single value for dropdown
global $pdo;
global $g_error;
$sql = "SELECT ddtext FROM dropdown WHERE ddid=? AND ddval=?";
$sth = $pdo->prepare($sql);
try {
$sth->execute([$ddid, $ddval]);
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
return '#err';
}
return $sth->fetchColumn();
}
// Functions to get option lists (key/value)
function db_get_options($ddid, $orderby = '', $short = False, $default = NULL) {
// returns list for dropdown
// if short is set the short value will be returned
global $pdo;
$list = array();
if ($default != NULL) {
$list[0] = $default;
}
if ($short) {
$sql = "SELECT ddval, ddshort";
} else {
$sql = "SELECT ddval, ddtext";
}
$sql .= " FROM dropdown WHERE ddid=?";
if ($orderby == 'ddtext') {
$sql .= ' ORDER BY ddtext';
} elseif ($orderby == 'sort') {
$sql .= ' ORDER BY sort';
} else {
$sql .= ' ORDER BY ddval';
}
$sth = $pdo->prepare($sql);
$sth->execute([$ddid]);
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $rec) {
$list[$rec[0]] = $rec[1];
}
return $list;
}
function db_get_opt_vessel() {
global $pdo;
$list = array();
$sth = $pdo->query("SELECT vid, vesselname, model FROM vessel ORDER BY vid");
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $row) {
$list[$rec[0]] = $rec[1];
}
return $list;
}
function db_get_opt_storage($vid) {
global $pdo;
global $g_error;
$list = array();
// exclude storage type "tank" from list
$sql = "SELECT sid, sname FROM storage WHERE vid=? AND stype<>1 ORDER BY sname";
$sth = $pdo->prepare($sql);
try {
$sth->execute([$vid]);
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
}
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $rec) {
$list[$rec[0]] = $rec[1];
}
return $list;
}
function db_get_opt_box($vid, $exclude=[]) {
global $pdo;
global $g_error;
$list = array();
$sql = "SELECT boxid, label, content "
. "FROM box INNER JOIN storage USING (sid) "
. "WHERE vid=? "
. "ORDER BY label";
$sth = $pdo->prepare($sql);
try {
$sth->execute([$vid]);
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
}
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $rec) {
if (! in_array($rec[0], $exclude)) {
$list[$rec[0]] = $rec[1] . ($rec[2] ? ' - '. $rec[2] : '');
}
}
return $list;
}
function db_get_opt_equip($vid, $default=NULL, $exclude=[]) {
global $pdo;
global $g_error;
if (isset($default)) {
$list = $default;
} else {
$list = array();
}
$sql = "SELECT eid, ename FROM equipment WHERE vid=? ORDER BY ename";
$sth = $pdo->prepare($sql);
try {
$sth->execute([$vid]);
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
}
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $rec) {
if (! in_array($rec[0], $exclude)) {
$list[$rec[0]] = $rec[1];
}
}
return $list;
}
function db_get_opt_manuf($default=NULL) {
global $pdo;
if (isset($default)) {
$list = $default;
} else {
$list = array();
}
$sql = "SELECT compid, compname FROM company WHERE comptype=2 ORDER BY compname";
$sth = $pdo->query($sql);
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $row) {
$list[$row[0]] = $row[1];
}
return $list;
}
function db_get_opt_supp($default=NULL) {
global $pdo;
if (isset($default)) {
$list = $default;
} else {
$list = array();
}
$sql = "SELECT compid, compname FROM company WHERE comptype=1 ORDER BY compname";
$sth = $pdo->query($sql);
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $row) {
$list[$row[0]] = $row[1];
}
return $list;
}
function db_get_opt_user($userid, $default=NULL) {
global $pdo;
if (isset($default)) {
$list = $default;
} else {
$list = array();
}
$sql = "SELECT userid, displayname FROM user WHERE userid>0 ORDER BY displayname";
$sth = $pdo->query($sql);
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $row) {
$list[$row[0]] = $row[1];
}
return $list;
}
function db_get_opt_proj($vid, $exclude=[], $default=NULL) {
// exclude is a list of project states
global $pdo;
global $g_error;
if (isset($default)) {
$list = $default;
} else {
$list = array();
}
$sql = "SELECT projid, projname FROM project WHERE vid=?";
$where = [];
foreach ($exclude as $excl) {
$where[] = "NOT FIND_IN_SET('$excl',projstate)";
}
if (! empty($where)) {
$sql .= ' AND '. implode(' AND ', $where);
}
$sql .= " ORDER BY projname";
$sth = $pdo->prepare($sql);
try {
$sth->execute([$vid]);
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
}
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $rec) {
$list[$rec[0]] = $rec[1];
}
return $list;
}
function db_get_filter($user, $sno, $fields = []) {
// if fields supplied empting missing field are created
global $pdo;
global $g_warning;
$flt = new stdClass();
$sth = $pdo->prepare("SELECT valstr FROM settings WHERE userid=? AND sno=?");
try {
$sth->execute([$user, $sno]);
$json = $sth->fetchColumn();
if ($json === false) {
// no settings record. create empty one for later updates
$sth = $pdo->prepare("INSERT INTO settings (userid, sno, valstr) VALUES (?, ?, '{}')");
$sth->execute([$user, $sno]);
} else {
$flt = json_decode($json);
}
// create missing fields
foreach ($fields as $f) {
if (!property_exists($flt, $f)) {
$flt->$f = null;
}
}
} catch (PDOexception $e) {
$g_warning->Add('SQL-Error: '. $e->getMessage());
$g_warning->PrintOut();
}
return $flt;
}
function db_get_default_storage($vesselid, $fallback=true) {
global $pdo;
global $g_error, $g_warning;
$sql = "SELECT sid_default FROM vessel WHERE vid=?";
$sth = $pdo->prepare($sql);
try {
$sth->execute([$vesselid]);
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
return false;
}
$sid = $sth->fetchColumn();
if ($sid == NULL && $fallback) {
// try to get another storage as last fallback
$g_warning->Add(_('No default storage defined for current vessel'));
$sql = "SELECT MIN(sid), sname FROM storage WHERE vid=?";
$sth = $pdo->prepare($sql);
try {
$sth->execute([$vesselid]);
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
return false;
}
$row = $sth->fetch(PDO::FETCH_NUM);
if ($row[0] == NULL) {
$g_error->Add('Error: No storage defined for current vessel');
return false;
}
$sid = $row[0];
$g_warning->Add(sprintf(_("Selected fallback storage '%s'"), $row[1]));
}
return $sid;
}
function date_to_sql($var) {
if (!isset($var) || $var == '') {
return NULL;
} else {
list($d, $m, $y) = explode('.', $var);
return sprintf("%04d-%02d-%02d", $y, $m, $d);
}
}
function float_to_sql($var) {
global $g_lconv;
if (!isset($var) || $var == '') {
return NULL;
} else {
// remove thousands separator
$var = str_replace($g_lconv['thousands_sep'], '', $var);
// force decimal point
if ($g_lconv['decimal_point'] != '.') {
$var = str_replace($g_lconv['decimal_point'], '.', $var);
}
return $var;
}
}
// ========== FORM FUNCTIONS ==================================================
function form_get_action() {
if (!isset($_POST['submit'])) {
if (isset($_GET['f'])) {
$submit = $_GET['f'];
// strip parameters
/* $pos = strpos($submit, '?');
if ($pos > 2) {
$submit = substr($submit, 0, $pos);
} */
} else {
$submit = NULL;
}
} else {
$submit = $_POST['submit'];
}
if (is_array($submit)) {
$submit = key($submit);
}
return strtolower($submit);
}
function form_create_input($fieldname, $label, $value) {
// TODO WIP
echo '
', "\n";
echo "
\n";
}
function form_create_text($fieldname, $label, $value) {
// TODO WIP
echo '
', "\n";
echo "
\n";
}
function form_create_check($fieldname, $label, $checked) {
// create single checkbox with assigned label
echo '
\n";
}
function form_create_checks($fieldname, $label, $optlist, $selected = []) {
// create multiple combined checkboxes with title
echo '';
}
// TODO DEPRECATED for touch multiple adjacent buttuns are not well suited.
function form_action_buttons($script, $id) {
echo "
";
echo '', "\n";
echo '', "\n";
echo "
\n";
}
function form_add_button($script, $id=NULL, $idname='id') {
echo '
\n";
}
function form_delete_buttons($script, $id, $token) {
echo '
', "\n";
echo '\n";
echo "
\n";
}
function form_tag_assignment($script, $id, $tags) {
echo '
';
echo '
', _('Tags'), "
\n";
echo '
', $tags, '
';
echo "
\n
";
echo '
', _('Tag assignment'), "
\n";
echo '
\n";
echo "
";
}
function filter_create_select($fieldname, $label, $optlist, $selval=NULL, $multiple=FALSE) {
// - Wenn multiple gesetzt ist, muß selval ein array sein
// ansonsten ein einfacher String
/* if ($multiple) {
if (!is_array($selval)) {
}
} */
echo '
', "\n";
echo '', "\n";
echo '\n";
echo "
";
}
function filter_create_checks($fieldname, $label, $optlist, $selected = []) {
// TODO WIP
echo '';
}
// ========== FORMAT FUNCTIONS ================================================
function format_float($val, $decimals = 2, $suffix = '') {
global $g_lconv;
if (!isset($val) || $val == '') {
return '';
}
return number_format($val, $decimals, $g_lconv['decimal_point'], $g_lconv['thousands_sep']) . ($suffix ? " $suffix" : '');
}
function format_currency($val) {
global $g_lconv;
if (!isset($val) || $val == '') {
return '';
}
if ($g_lconv['currency_symbol'] == '$') {
return '$'.number_format($val, 2, $g_lconv['decimal_point'], $g_lconv['thousands_sep']);
} else {
return number_format($val, 2, $g_lconv['decimal_point'], $g_lconv['thousands_sep']) . ' ' . $g_lconv['currency_symbol'];
}
}
function format_color($color) {
$colstr = '#' . $color . '' ;
return $colstr;
}
function format_filesize($size, $format=2) {
switch ($format) {
case 1: // short
if ($size < 1024) {
$size_string = sprintf(_('%d B'), $size);
} elseif ($size < 1048576) {
$size_string = sprintf(_('%.1f kB'), $size/1024);
} else {
$size_string = sprintf(_('%.1f MB'), $size/1048576);
}
break;
case 2: // medium
if ($size < 1024) {
$size_string = sprintf(_('%d Byte'), $size);
} elseif ($size < 1048576) {
$size_string = sprintf(_('%.1f kByte'), $size/1024);
} else {
$size_string = sprintf(_('%.1f MByte'), $size/1048576);
}
break;
case 3: // long
if ($size < 1024) {
$size_string = sprintf(_('%d Byte'), $size);
} elseif ($size < 1048576) {
$size_string = sprintf(_('approx. %.1f kByte'), $size/1024);
} else {
$size_string = sprintf(_('approx. %.1f MByte'), $size/1048576);
}
break;
default:
$size_string = trim($size);
}
return $size_string;
}
function format_measurement($n, $unit, $v1, $v2, $v3) {
$m = '';
switch ($n) {
case 1:
$m = "$v1 $unit";
break;
case 2:
$m = "$v1×$v2 $unit";
break;
case 3:
$m = "$v1×$v2×$v3 $unit";
break;
}
return $m;
}
// ========== COMMON FUNCTIONS ================================================
function header_location($location, $message=NULL) {
if (is_array($message)) {
$valid_keys = array('succ', 'info', 'warn', 'err');
foreach ($message as $k => $v) {
if (in_array($k, $valid_keys)) {
$_SESSION['message'][$k] = $v;
}
}
}
header("Location: $location");
exit;
}
function pgettext($context, $msgid) {
// implement missing function
global $g_textdomain;
$ctxstr = "{$context}\004{$msgid}";
$translation = dcgettext($g_textdomain, $ctxstr, LC_MESSAGES);
if ($translation == $ctxstr) {
return $msgid;
} else {
return $translation;
}
}
function get_color_brightness($color, $default=0.5) {
// returns a value between 0 and 1
// color is a 6 char hex string
if (strlen($color) != 6) {
return $default;
}
list($red, $green, $blue) = array_map('hexdec', str_split($color, 2));
$red = $red / 255 * 0.2126;
$green = $green / 255 * 0.7152;
$blue = $blue / 255 * 0.0722;
return $red + $green + $blue;
}
function page_caption_search($caption) {
// print page caption with searchbox
?>
=$caption?>
' . "\n";
$out .= '
' . "\n";
// First Prev ... Next Last
// TODO build entries for first, prev, next last
if ($page > 1) {
// Go to first page or previous page
$out .= '