Config class rewrite (#6965)

* Use a singleton pattern in the database class to re-use the database object inside the permission_exists function.
This commit is contained in:
frytimo 2024-04-27 22:22:20 -03:00 committed by GitHub
parent 8a30f04125
commit 0b8edef82c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 368 additions and 141 deletions

View File

@ -124,7 +124,7 @@
$sql .= "lower(default_setting_category) = :default_setting_category ";
$parameters['default_setting_category'] = strtolower($default_setting_category);
}
$database = new database;
$database = database::new();
$num_rows = $database->select($sql, $parameters ?? null, 'column');
//get the list
@ -148,7 +148,6 @@
}
$sql .= order_by($order_by, $order, 'default_setting_category, default_setting_subcategory, default_setting_order', 'asc');
//$sql .= limit_offset($rows_per_page, $offset ?? ''); //$offset is always null
$database = new database;
$default_settings = $database->select($sql, $parameters ?? null, 'all');
unset($sql, $parameters);
@ -173,7 +172,6 @@
$sql .= ") as quantity ";
$sql .= "from v_default_settings as d1 ";
$sql .= "order by d1.default_setting_category asc ";
$database = new database;
$rows = $database->select($sql, $parameters ?? null, 'all');
if (!empty($rows) && @sizeof($rows) != 0) {
foreach ($rows as $row) {
@ -462,7 +460,6 @@
$sql = "select * from v_menus ";
$sql .= "where menu_uuid = :menu_uuid ";
$parameters['menu_uuid'] = $row['default_setting_value'];
$database = new database;
$sub_result = $database->select($sql, $parameters ?? null, 'all');
foreach ($sub_result as &$sub_row) {
echo $sub_row["menu_language"]." - ".$sub_row["menu_name"]."\n";

View File

@ -1,155 +1,345 @@
<?php
/**
* config
*
* @method get config.php
* @method find find the path to the config.php file
* @method exists determin if the the config.php file exists
* config class loads configuration from the file system
* @param string $db_type Type of database
* @param string $db_driver Alias of type
* @param string $db_host Host to connect to
* @param string $db_path Path of the database if it is file system based
* @param string $db_file File name of the database if it is file system based
* @param string $db_port Port to connect to
* @param string $db_name Name of the database
* @param string $db_sslmode SSL Mode to use
* @param string $db_cert_authority The certificate authority
* @param string $db_secure If the database is using a secure connection
* @param string $db_username Username credentials to connect with
* @param string $db_password Password credentials to connect with
* @param string $config_path Configuration path currently in use
* @param string $config_file Configuration file currently in use
* @param string $config_path_and_filename Full path and configuration file currently in use
* @internal the @param statements are used because they match the magic __get function that allows those to be accessed publicly
*/
class config {
final class config {
// Full path and filename of config.conf
private $file;
// The internal array that holds the configuration in the config.conf file
private $configuration;
/**
* database variables and config path
* Configuration object used to hold a single instance
* @var array
*/
public $db_type;
public $db_name;
public $db_username;
public $db_password;
public $db_sslmode;
public $db_host;
public $db_path;
public $db_port;
public $db_secure;
public $db_cert_authority;
public $config_path;
public static $config = null;
/**
* Called when the object is created
* Loads the framework configuration file
*/
public function __construct() {
//place holder
public function __construct(?string $file = '') {
//initialize configuration array to be an empty array
$this->configuration = [];
//check if the config file was found
if (empty($file)) {
//locate the conf file
$file = self::find();
}
//remember the fullpath and filename
$this->file = $file;
//load the conf file
if (file_exists($file)) {
$this->read();
}
//set the server variables
$this->define_project_paths();
}
/**
* Determine whether the config file exists
* @var string $db_type - type of database
* @var string $db_name - name of the database
* @var string $db_username - username to access the database
* @var string $db_password - password to access the database
* @var string $db_host - hostname of the database server
* @var string $db_path - path of the database file
* @var string $db_port - network port to connect to the database
* @var bool $db_secure - whether or not to connect with SSL
* @var string $db_cert_authority - location of certificate authority
* Magic method to allow backward compatibility for variables such as db_type.
* <p>This will allow using config object with the syntax of:<br>
* $config = new config();<br>
* $db_type = $config->db_type;<br></p>
* <p>Note:<br>
* The <i>InvalidArgumentException</i> is thrown if there is no such variable accessed such as:<br>
* $config = new config();<br>
* $db_function = $config->db_function();
* </p>
* <p>This is ensure that any invalid code is detected and fixed.</p>
* @param string $name Name of the object property
* @return string Returns the value as a string
*/
public function get() {
//find the config_path
$config_path = $this->find();
public function __get(string $name): string {
switch($name) {
case 'db_type':
case 'db_driver':
return $this->configuration['database.0.type'] ?? '';
case 'db_path':
case 'path':
return $this->configuration['database.0.path'] ?? '';
case 'db_host':
return $this->configuration['database.0.host'] ?? '';
case 'db_port':
return $this->configuration['database.0.port'] ?? '';
case 'db_name':
return $this->configuration['database.0.name'] ?? '';
case 'db_sslmode':
return $this->configuration['database.0.sslmode'] ?? 'prefer';
case 'db_cert_authority':
return $this->configuration['database.0.cert_authority'] ?? '';
case 'db_secure':
return $this->configuration['database.0.secure'] ?? 'false';
case 'db_username':
case 'username':
return $this->configuration['database.0.username'] ?? '';
case 'db_password':
case 'password':
return $this->configuration['database.0.password'] ?? '';
case 'db_file':
return $this->configuration['database.0.file'] ?? '';
case 'config_path':
return $this->path();
case 'config_filename':
return $this->filename();
case 'config_path_and_filename':
case 'config_file':
return $this->path_and_filename();
default:
if (property_exists($this, $name)) {
return $this->{$name};
}
elseif (array_key_exists($name, $this->configuration)) {
return $this->configuration[$name];
}
}
return "";
}
//add the document root to the include path
$conf = parse_ini_file($config_path);
set_include_path($conf['document.root']);
/**
* Returns the string representation of the configuration file
* @return string configuration
*/
public function __toString(): string {
$string_builder = "";
foreach ($this->configuration as $key => $value) {
$string_builder .= "$key = '$value'\n";
}
return $string_builder;
}
//check if the config file exists
$config_exists = file_exists($config_path) ? true : false;
// loads the config.conf file
public function read() {
//check if include is needed
if (substr($this->file, 0, -4) === '.php') {
//allow global variables to be set in the old config.php file
global $db_type, $db_host, $db_port, $db_name, $db_username, $db_password, $db_path;
global $db_sslmode, $db_secure, $db_cert_authority;
//load the config.php file
require_once $this->file;
//convert the old properties to the new standard
if (isset($db_type)) {
$this->configuration['database.0.type'] = $db_type;
} else {
$this->configuration['database.0.type'] = 'pgsql';
}
if (isset($db_path)) {
$this->configuration['database.0.path'] = $db_path;
} else {
$this->configuration['database.0.path'] = '';
}
if (isset($db_host)) {
$this->configuration['database.0.host'] = $db_host;
}
if (isset($db_port)) {
$this->configuration['database.0.port'] = $db_port;
}
if (isset($db_name)) {
$this->configuration['database.0.name'] = $db_name;
}
if (isset($db_username)) {
$this->configuration['database.0.username'] = $db_username;
}
if (isset($db_password)) {
$this->configuration['database.0.password'] = $db_password;
}
if (isset($db_sslmode)) {
$this->configuration['database.0.sslmode'] = $db_sslmode;
} else {
$this->configuration['database.0.sslmode'] = 'prefer';
}
if (isset($db_secure)) {
$this->configuration['database.0.secure'] = $db_secure;
}
if (isset($db_cert_authority)) {
$this->configuration['database.0.cert_authority'] = $db_cert_authority;
}
//remove from the global namespace
unset($db_type, $db_host, $db_port, $db_name, $db_username, $db_password, $db_sslmode, $db_secure, $db_cert_authority);
}
else {
//save the loaded and parsed conf file to the object
$this->configuration = parse_ini_file($this->file);
}
}
// set project paths if not already defined
private function define_project_paths() {
// Load the document root
$doc_root = $this->get('document.root', '/var/www/fusionpbx');
$doc_path = $this->get('document.path', '');
//set the server variables and define project path constant
$_SERVER["DOCUMENT_ROOT"] = $conf['document.root'];
$_SERVER["PROJECT_ROOT"] = $conf['document.root'];
$_SERVER["PROJECT_PATH"] = $conf['project.path'];
if (isset($conf['project.path'])) {
$_SERVER["PROJECT_ROOT"] = $conf['document.root'].'/'.$conf['project.path'];
if (!defined('PROJECT_ROOT')) { define("PROJECT_ROOT", $conf['document.root'].'/'.$conf['project.path']); }
if (!defined('PROJECT_PATH')) { define("PROJECT_PATH", $conf['project.path']); }
if (!empty($doc_path)) {
if (!defined('PROJECT_PATH')) { define("PROJECT_PATH", $doc_path); }
if (!defined('PROJECT_ROOT')) { define("PROJECT_ROOT", $doc_root.'/'.$doc_path); }
}
else {
if (!defined('PROJECT_ROOT')) { define("PROJECT_ROOT", $conf['document.root']); }
if (!defined('PROJECT_PATH')) { define("PROJECT_PATH", ''); }
if (!defined('PROJECT_ROOT')) { define("PROJECT_ROOT", $doc_root); }
}
//add the database settings
$this->db_type = $conf['database.0.type'];
$this->db_name = $conf['database.0.name'];
$this->db_username = $conf['database.0.username'];
$this->db_password = $conf['database.0.password'];
$this->db_sslmode = $conf['database.0.sslmode'] ?? '';
$this->db_secure = $conf['database.0.secure'] ?? '';
$this->db_cert_authority = $conf['database.0.db_cert_authority'] ?? '';
$this->db_host = $conf['database.0.host'];
$this->db_path = $conf['database.0.path'] ?? '';
$this->db_port = $conf['database.0.port'];
// internal definitions to the framework
$_SERVER["PROJECT_PATH"] = PROJECT_PATH;
$_SERVER["PROJECT_ROOT"] = PROJECT_ROOT;
// tell php where the framework is
$_SERVER["DOCUMENT_ROOT"] = PROJECT_ROOT;
// have php search for any libraries in the now defined root
set_include_path(PROJECT_ROOT);
}
/**
* Find the path to the config.php
* Find the path to the config.conf file
* @var string $config_path - full path to the config.php file
*/
public function find() {
public static function find(): string {
//define the file variable
$file = "";
//find the file
if (file_exists("/etc/fusionpbx/config.conf")) {
$this->config_path = "/etc/fusionpbx/config.conf";
}
elseif (file_exists("/usr/local/etc/fusionpbx/config.conf")) {
$this->config_path = "/usr/local/etc/fusionpbx/config.conf";
}
elseif (file_exists($_SERVER["PROJECT_ROOT"]."/resources/config.php")) {
$this->config_path = $_SERVER["PROJECT_ROOT"]."/resources/config.php";
}
elseif (file_exists("/etc/fusionpbx/config.php")) {
$this->config_path = "/etc/fusionpbx/config.php";
}
elseif (file_exists("/usr/local/etc/fusionpbx/config.php")) {
$this->config_path = "/usr/local/etc/fusionpbx/config.php";
}
else {
$this->config_path = '';
}
//return the path
return $this->config_path;
if (file_exists("/etc/fusionpbx/config.conf")) {
$file = "/etc/fusionpbx/config.conf";
}
elseif (file_exists("/usr/local/etc/fusionpbx/config.conf")) {
$file = "/usr/local/etc/fusionpbx/config.conf";
}
elseif (file_exists("/etc/fusionpbx/config.php")) {
$file = "/etc/fusionpbx/config.php";
}
elseif (file_exists("/usr/local/etc/fusionpbx/config.php")) {
$file = "/usr/local/etc/fusionpbx/config.php";
}
elseif (file_exists(dirname(__DIR__, 2) . "/resources/config.php")) {
//use the current web directory to find it as a last resort
$file = "/var/www/fusionpbx/resources/config.php";
}
return $file;
}
/**
* Determine whether the config file exists
* Get a configuration value using a key in the configuration file
* @param string|null $key Match key on the left hand side of the '=' in the config file. If $key is null the default value is returned
* @param string $default_value if no matching key is found, then this value will be returned
* @return string returns a value in the config.conf file or an empty string
*/
public function exists() {
$this->find();
if (!empty($this->config_path)) {
return true;
public function get(string $key, string $default_value = ''): string {
if (!empty($this->__get($key))) {
return $this->__get($key);
}
else {
return false;
return $default_value;
}
/**
* Returns the config path or an empty string
* @return string
*/
public function path(): string {
return dirname($this->file);
}
/**
* Returns the file name only of the configuration file
* @return string
*/
public function filename(): string {
return basename($this->file);
}
/**
* Returns the path and the file name
* @return string
*/
public function path_and_filename(): string {
return $this->file;
}
/**
* Returns if the config class has a loaded configuration or not
* @return bool True if configuration has loaded and false if it is empty
*/
public function is_empty(): bool {
return count($this->configuration) === 0;
}
/**
* Returns the array of configuration settings
* @return array
*/
public function configuration(): array {
return $this->configuration;
}
/**
* Ensures the configuration file is loaded only once
* @return config
*/
public static function load(?string $file = ''): config {
if (self::$config === null) {
self::$config = new config($file);
}
return self::$config;
}
}
/*
$config = new config;
$config_exists = $config->exists();
$config_path = $config->find();
$config->get();
$db_type = $config->db_type;
$db_name = $config->db_name;
$db_username = $config->db_username;
$db_password = $config->db_password;
$db_host = $config->db_host;
$db_path = $config->db_path;
$db_port = $config->db_port;
echo "config_path: ".$config_path."\n";
if ($config_exists) {
echo "config_exists: true\n";
} else {
echo "config_exists: false\n";
}
echo "db_type: ".$db_type."\n";
echo "db_name: ".$db_name."\n";
echo "db_username: ".$db_username."\n";
echo "db_password: ".$db_password."\n";
echo "db_host: ".$db_host."\n";
echo "db_path: ".$db_path."\n";
echo "db_port: ".$db_port."\n";
*/
?>
/*
//Examples:
//~~~~~~~~
$config = new config;
echo "Config path: " . $config->path() . "\n";
echo "Config file: " . $config->filename() . "\n";
echo "Full path and filename: " . $config->path_and_filename() . "\n";
// show old style configuration options
echo "db_type: ".$config->db_type."\n";
echo "db_name: ".$config->db_name."\n";
echo "db_username: ".$config->db_username."\n";
echo "db_password: ".$config->db_password."\n";
echo "db_host: ".$config->db_host."\n";
echo "db_path: ".$config->db_path."\n";
echo "db_port: ".$config->db_port."\n";
// use current style configuration options even on old config.php
echo "database.0.type: " . $config->get('database.0.type') . "\n";
// use a default value
echo "admin.name: " . $config->value('admin.name', 'admin') . "\n";
// get all configuration options by printing the object
echo "config settings: " . $config . "\n";
// save the configuration options to a file
file_put_contents('/etc/fusionpbx/config.conf', $config);
// get all configuration options as an array
var_dump($config->configuration());
//*/

View File

@ -256,24 +256,61 @@
*/
public $message;
/**
* Config object used to get the database connection params
* @var config
*/
private $config;
/**
* SSL Mode used to connect to the database
* @var string prefer or verify-ca. Default is 'prefer'
*/
public $ssl_mode;
/**
* Singleton type class
* @var database
*/
private $database;
/**
* Called when the object is created
* @param array $params Optional
*/
public function __construct(array $params = []) {
//set the domain_uuid
if (isset($params['domain_uuid']) && is_uuid($params['domain_uuid'])) {
$this->domain_uuid = $domain_uuid;
if (isset($params['config'])) {
$config = $params['config'];
}
elseif (isset($_SESSION['domain_uuid']) && is_uuid($_SESSION['domain_uuid'])) {
$this->domain_uuid = $_SESSION['domain_uuid'];
else {
$config = new config();
}
//set the user_uuid
if (isset($params['user_uuid']) && is_uuid($params['user_uuid'])) {
$this->user_uuid = $user_uuid;
//driver and type point to the same value
$this->driver = $config->get('database.0.type', 'pgsql');
$this->driver = $config->get('database.0.type', 'pgsql');
$this->type = $config->get('database.0.type', 'pgsql');
$this->host = $config->get('database.0.host', '127.0.0.1');
$this->port = $config->get('database.0.port', '5432');
$this->username = $config->get('database.0.username', 'fusionpbx');
$this->password = $config->get('database.0.password', 'fusionpbx');
$this->db_name = $config->get('database.0.name', 'fusionpbx');
$this->db_secure = $config->get('database.0.secure', '');
$this->db_cert_authority = $config->get('database.0.cert_authority', '');
$this->ssl_mode = $config->get('database.0.ssl_mode', '');
//save the reference to the single instance of the config to this object
$this->config = $config;
//connect to the database now
$this->connect();
if (!isset($this->domain_uuid) && isset($_SESSION['domain_uuid'])) {
$this->domain_uuid = $_SESSION['domain_uuid'];
}
elseif (isset($_SESSION['user_uuid']) && is_uuid($_SESSION['user_uuid'])) {
$this->user_uuid = $_SESSION['user_uuid'];
//allow passed domain_uuid in the constructor to override the session domain
if (isset($params['domain_uuid'])) {
$this->domain_uuid = $params['domain_uuid'];
}
}
@ -420,9 +457,6 @@
*/
public function connect() {
//includes files
require dirname(__DIR__, 2) . "/resources/require.php";
//get the database connection settings
//$db_type = $conf['database.0.type'];
//$db_host = $conf['database.0.host'];
@ -523,7 +557,7 @@
if (!empty($this->host)) {
if (empty($this->port)) { $this->port = "5432"; }
if ($this->db_secure === true) {
$this->db = new PDO("pgsql:host=$this->host port=$this->port dbname=$this->db_name user=$this->username password=$this->password sslmode=verify-ca sslrootcert=$this->db_cert_authority");
$this->db = new PDO("pgsql:host=$this->host port=$this->port dbname=$this->db_name user=$this->username password=$this->password sslmode=$this->ssl_mode sslrootcert=$this->db_cert_authority");
}
else {
$this->db = new PDO("pgsql:host=$this->host port=$this->port dbname=$this->db_name user=$this->username password=$this->password");
@ -669,8 +703,12 @@
//if unable to connect to the database
if (!$this->db) {
$backtrace = debug_backtrace();
echo "Connection Failed<br />\n";
echo "line number ".__line__."<br />\n";
echo "<pre>";
print_r($backtrace);
echo "</pre>";
exit;
}
@ -3043,9 +3081,11 @@
* @see database::connect()
*/
public static function new() {
$db = new database();
$db->connect();
return $db;
if (self::$database === null)
self::$database = new database();
self::$database->connect();
}
return self::$database;
}
} //class database
@ -3111,4 +3151,4 @@
echo $database->count();
*/
?>
?>

View File

@ -607,8 +607,7 @@ if (!class_exists('domains')) {
//get the variables
$config = new config;
$config_path = $config->find();
$config->get();
$config_path = $config->config_file;
//get the list of installed apps from the core and app directories (note: GLOB_BRACE doesn't work on some systems)
$config_list_1 = glob($_SERVER["DOCUMENT_ROOT"].PROJECT_PATH."/*/*/app_config.php");

View File

@ -324,7 +324,8 @@
if (!function_exists('permission_exists')) {
function permission_exists($permission_name, $operator = 'or') {
$permission = new permissions;
$database = database::new();
$permission = new permissions($database);
return $permission->exists($permission_name);
}