mytinytodo/src/includes/class.config.php
2022-02-01 16:35:07 +03:00

293 lines
No EOL
8.2 KiB
PHP

<?php
/*
This file is a part of myTinyTodo.
(C) Copyright 2021 Max Pozdeev <maxpozdeev@gmail.com>
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
*/
class Config
{
/** @var bool */
public static $noDatabase = false;
/** @var array[] */
private static $dbparams = array(
# Database type: sqlite or mysql
'db.type' => array('default'=>'sqlite', 'type'=>'s'),
# Specific database api
'db.driver' => array('default'=>'', 'type'=>'s'),
# Mysql connection settings
'db.host' => array('default'=>'localhost', 'type'=>'s'),
'db.user' => array('default'=>'mtt', 'type'=>'s'),
'db.password' => array('default'=>'mtt', 'type'=>'s'),
'db.name' => array('default'=>'mytinytodo', 'type'=>'s'),
# Prefix for table names
'db.prefix' => array('default'=>'', 'type'=>'s')
);
/** @var array[] */
private static $convert = array(
'mysql.host' => 'db.host',
'mysql.user' => 'db.user',
'mysql.password' => 'db.password',
'mysql.db' => 'db.name',
'db' => 'db.type',
'prefix' => 'db.prefix'
);
/** @var array[] */
public static $params = array(
# These two parameters are used when mytinytodo index.php called not from installation directory
# 'url' - URL where index.php is called from (ex.: http://site.com/todo.php)
# 'mtt_url' - directory URL where mytinytodo is installed (with trailing slash) (ex.: http://site.com/lib/mytinytodo/)
'url' => array('default'=>'', 'type'=>'s'),
'mtt_url' => array('default'=>'', 'type'=>'s'),
# Top title
'title' => array('default'=>'', 'type'=>'s'),
# Language pack
'lang' => array('default'=>'en', 'type'=>'s'),
# Password to protect your tasks from modification,
# leave empty that everyone could read/write todolist
'password' => array('default'=>'', 'type'=>'s'),
# Smart Syntax enabled flag
'smartsyntax' => array('default'=>1, 'type'=>'i'),
# Default Time zone
'timezone' => array('default'=>'UTC', 'type'=>'s'),
# To disable auto adding selected tag set value to 0
'autotag' => array('default'=>1, 'type'=>'i'),
# duedate calendar format: 1 => y-m-d (default), 2 => m/d/y, 3 => d.m.y
'duedateformat' => array('default'=>1, 'type'=>'i'),
# First day of week: 0-Sunday, 1-Monday, 2-Tuesday, .. 6-Saturday
'firstdayofweek' => array('default'=>1, 'type'=>'i', 'options'=>array(0,1,2,3,4,5,6)),
# Date/time formats
'clock' => array('default'=>24, 'type'=>'i', 'options'=>array(12,24)),
'dateformat' => array('default'=>'j M Y', 'type'=>'s'),
'dateformat2' => array('default'=>'n/j/y', 'type'=>'s'),
'dateformatshort' => array('default'=>'j M', 'type'=>'s'),
'template' => array('default'=>'default', 'type'=>'s'),
# Show task date in list
'showdate' => array('default'=>0, 'type'=>'i'),
# Use Markdown syntax for notes. Set to 'v1' to use old v1.6 syntax.
'markup' => array('default'=>'markdown', 'type'=>'s'),
);
/** @var mixed[] */
private static $config = array();
/**
*
* @param mixed[] $config
* @return void
*/
public static function loadConfigV14(array $config)
{
foreach ($config as $key => $val) {
if (isset(self::$convert[$key])) {
$key = self::$convert[$key];
}
elseif ($key == 'mysqli' && (int)$val != 0) {
$key = 'db.driver';
$val = 'mysqli';
}
// if (!isset(self::$dbparams[$key])) {
// throw new Exception("Unknown key: $key");
// }
self::$config[$key] = $val;
}
}
/**
*
* @return void
* @throws Exception
*/
public static function load()
{
if (self::$noDatabase) {
return;
}
$j = self::requestDomain('config.json');
foreach ($j as $key=>$val) {
// Ignore params for database config
if ( !isset(self::$dbparams[$key]) ) {
self::$config[$key] = $val;
}
}
}
/**
*
* @param string $key
* @return mixed
*/
public static function get($key)
{
if (isset(self::$config[$key])) return self::$config[$key];
elseif (isset(self::$params[$key])) return self::$params[$key]['default'];
elseif (isset(self::$dbparams[$key])) return self::$dbparams[$key]['default'];
else return null;
}
/**
*
* @param string $key
* @return string|null
*/
public static function getUrl($key)
{
$url = '';
if ( isset(self::$config[$key]) ) $url = self::$config[$key];
else if( isset(self::$params[$key]) ) $url = self::$params[$key]['default'];
else return null;
return str_replace( ["\r","\n"], '', $url );
}
/**
*
* @param string $key
* @param mixed $value
* @return void
* @throws Exception
*/
public static function set($key, $value)
{
if ($key == "db.prefix" && $value != "" && !preg_match("/^[a-zA-Z0-9_]+$/", $value)) {
throw new Exception("Incorrect table prefix. Can contain only latin letters, digits and underscore character.");
}
self::$config[$key] = $value;
}
/**
*
* @return void
* @throws Exception
*/
public static function save()
{
$j = array();
foreach (self::$params as $param => $v)
{
if ( !isset(self::$config[$param]) ) $val = $v['default'];
elseif ( isset($v['options']) && !in_array(self::$config[$param], $v['options'])) $val = $v['default'];
else $val = self::$config[$param];
if ($v['type']=='i') $val = (int)$val;
else $val = strval($val);
$j[$param] = $val;
}
self::saveDomain('config.json', $j);
}
/**
*
* @param string $key
* @return array
* @throws Exception
*/
public static function requestDomain($key)
{
$db = DBConnection::instance();
$json = $db->sq("SELECT param_value FROM {$db->prefix}settings WHERE param_key = ?", array($key));
if (!$json) return array();
$j = json_decode($json, true);
return $j;
}
/**
*
* @param string $key
* @param array $array
* @return void
* @throws Exception
*/
public static function saveDomain($key, $array)
{
$json = json_encode($array, JSON_PRETTY_PRINT);
$db = DBConnection::instance();
$keyExists = $db->sq("SELECT COUNT(param_key) FROM {$db->prefix}settings WHERE param_key = ?", array($key) );
if ($keyExists) {
$db->ex("UPDATE {$db->prefix}settings SET param_value = ? WHERE param_key = ?", array($json,$key) );
}
else {
$db->ex("INSERT INTO {$db->prefix}settings (param_key,param_value) VALUES (?,?)", array($key,$json) );
}
}
public static function defineDbConstants()
{
define("MTT_DB_TYPE", self::get('db.type'));
define("MTT_DB_HOST", self::get('db.host'));
define("MTT_DB_USER", self::get('db.user'));
define("MTT_DB_PASSWORD", self::get('db.password'));
define("MTT_DB_NAME", self::get('db.name'));
define("MTT_DB_PREFIX", self::get('db.prefix'));
if ( self::get('db.driver') != '' ) {
define("MTT_DB_DRIVER", self::get('db.driver'));
}
}
public static function dbConfigAsFileContents(): string
{
$a = array();
$a[] = "<?php\n";
$a[] = "// myTinyTodo Database connection configuration\n";
$a[] = self::prepareDbDefine("MTT_DB_TYPE", self::get('db.type')) . "\n";
$a[] = self::prepareDbDefine("MTT_DB_HOST", self::get('db.host')) . "\n";
$a[] = self::prepareDbDefine("MTT_DB_USER", self::get('db.user')) . "\n";
$a[] = self::prepareDbDefine("MTT_DB_PASSWORD", self::get('db.password')) . "\n";
$a[] = self::prepareDbDefine("MTT_DB_NAME", self::get('db.name')) . "\n";
$a[] = self::prepareDbDefine("MTT_DB_PREFIX", self::get('db.prefix')) . "\n";
$a[] = self::prepareDbDefine("MTT_DB_DRIVER", self::get('db.driver')) . "\n";
return implode("\n", $a);
}
private static function prepareDbDefine(string $key, string $value): string
{
if (!preg_match("/^[a-zA-Z0-9_]+$/", $key)) {
throw new Exception("Unexpected constant name: ". $key);
}
if (preg_match('~\R~', $value)) {
throw new Exception("Unexpected constant value: ". $value);
}
return "define(\"$key\", \"". str_replace(
array("\\", "'", "\""),
array("\\\\", "\\'", "\\\""),
$value )
. "\");";
}
public static function saveDbConfig()
{
$contents = self::dbConfigAsFileContents();
$f = fopen(MTTPATH. 'config.php', 'w');
if ($f === false) throw new Exception("Error while saving config file");
fwrite($f, $contents);
fclose($f);
//Reset Zend OPcache
//opcache_get_status() sometimes crashes
if (function_exists("opcache_invalidate") && 0 != (int)opcache_get_configuration()["directives"]["opcache.enable"]) {
opcache_invalidate(MTTPATH. 'config.php', true);
}
}
}
?>