config.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <?php
  2. /**
  3. * config class loads configuration from the file system
  4. * @param string $db_type Type of database
  5. * @param string $db_driver Alias of type
  6. * @param string $db_host Host to connect to
  7. * @param string $db_path Path of the database if it is file system based
  8. * @param string $db_file File name of the database if it is file system based
  9. * @param string $db_port Port to connect to
  10. * @param string $db_name Name of the database
  11. * @param string $db_sslmode SSL Mode to use
  12. * @param string $db_cert_authority The certificate authority
  13. * @param string $db_secure If the database is using a secure connection
  14. * @param string $db_username Username credentials to connect with
  15. * @param string $db_password Password credentials to connect with
  16. * @param string $config_path Configuration path currently in use
  17. * @param string $config_file Configuration file currently in use
  18. * @param string $config_path_and_filename Full path and configuration file currently in use
  19. * @internal the @param statements are used because they match the magic __get function that allows those to be accessed publicly
  20. */
  21. final class config {
  22. // Full path and filename of config.conf
  23. private $file;
  24. // The internal array that holds the configuration in the config.conf file
  25. private $configuration;
  26. /**
  27. * Configuration object used to hold a single instance
  28. * @var array
  29. */
  30. public static $config = null;
  31. /**
  32. * Loads the framework configuration file
  33. */
  34. public function __construct(string $file = '') {
  35. //initialize configuration array to be an empty array
  36. $this->configuration = [];
  37. //check if the config file was found
  38. if (empty($file)) {
  39. //locate the conf file
  40. $file = self::find();
  41. }
  42. //remember the fullpath and filename
  43. $this->file = $file;
  44. //load the conf file
  45. if (file_exists($file)) {
  46. $this->read();
  47. }
  48. //set the server variables
  49. $this->define_project_paths();
  50. }
  51. /**
  52. * Magic method to allow backward compatibility for variables such as db_type.
  53. * <p>This will allow using config object with the syntax of:<br>
  54. * $config = new config();<br>
  55. * $db_type = $config->db_type;<br></p>
  56. * <p>Note:<br>
  57. * The <i>InvalidArgumentException</i> is thrown if there is no such variable accessed such as:<br>
  58. * $config = new config();<br>
  59. * $db_function = $config->db_function();
  60. * </p>
  61. * <p>This is ensure that any invalid code is detected and fixed.</p>
  62. * @param string $name Name of the object property
  63. * @return string Returns the value as a string
  64. */
  65. public function __get(string $name): string {
  66. switch($name) {
  67. case 'db_type':
  68. case 'db_driver':
  69. return $this->configuration['database.0.type'] ?? '';
  70. case 'db_path':
  71. case 'path':
  72. return $this->configuration['database.0.path'] ?? '';
  73. case 'db_host':
  74. return $this->configuration['database.0.host'] ?? '';
  75. case 'db_port':
  76. return $this->configuration['database.0.port'] ?? '';
  77. case 'db_name':
  78. return $this->configuration['database.0.name'] ?? '';
  79. case 'db_sslmode':
  80. return $this->configuration['database.0.sslmode'] ?? 'prefer';
  81. case 'db_cert_authority':
  82. return $this->configuration['database.0.cert_authority'] ?? '';
  83. case 'db_secure':
  84. return $this->configuration['database.0.secure'] ?? 'false';
  85. case 'db_username':
  86. case 'username':
  87. return $this->configuration['database.0.username'] ?? '';
  88. case 'db_password':
  89. case 'password':
  90. return $this->configuration['database.0.password'] ?? '';
  91. case 'db_file':
  92. return $this->configuration['database.0.file'] ?? '';
  93. case 'config_path':
  94. return $this->path();
  95. case 'config_filename':
  96. return $this->filename();
  97. case 'config_path_and_filename':
  98. case 'config_file':
  99. return $this->path_and_filename();
  100. default:
  101. if (property_exists($this, $name)) {
  102. return $this->{$name};
  103. }
  104. elseif (array_key_exists($name, $this->configuration)) {
  105. return $this->configuration[$name];
  106. }
  107. }
  108. return "";
  109. }
  110. /**
  111. * Returns the string representation of the configuration file
  112. * @return string configuration
  113. */
  114. public function __toString(): string {
  115. $string_builder = "";
  116. foreach ($this->configuration as $key => $value) {
  117. $string_builder .= "$key = '$value'\n";
  118. }
  119. return $string_builder;
  120. }
  121. // loads the config.conf file
  122. public function read() {
  123. //check if include is needed
  124. if (substr($this->file, 0, -4) === '.php') {
  125. //allow global variables to be set in the old config.php file
  126. global $db_type, $db_host, $db_port, $db_name, $db_username, $db_password, $db_path;
  127. global $db_sslmode, $db_secure, $db_cert_authority;
  128. //load the config.php file
  129. require_once $this->file;
  130. //convert the old properties to the new standard
  131. if (isset($db_type)) {
  132. $this->configuration['database.0.type'] = $db_type;
  133. } else {
  134. $this->configuration['database.0.type'] = 'pgsql';
  135. }
  136. if (isset($db_path)) {
  137. $this->configuration['database.0.path'] = $db_path;
  138. } else {
  139. $this->configuration['database.0.path'] = '';
  140. }
  141. if (isset($db_host)) {
  142. $this->configuration['database.0.host'] = $db_host;
  143. }
  144. if (isset($db_port)) {
  145. $this->configuration['database.0.port'] = $db_port;
  146. }
  147. if (isset($db_name)) {
  148. $this->configuration['database.0.name'] = $db_name;
  149. }
  150. if (isset($db_username)) {
  151. $this->configuration['database.0.username'] = $db_username;
  152. }
  153. if (isset($db_password)) {
  154. $this->configuration['database.0.password'] = $db_password;
  155. }
  156. if (isset($db_sslmode)) {
  157. $this->configuration['database.0.sslmode'] = $db_sslmode;
  158. } else {
  159. $this->configuration['database.0.sslmode'] = 'prefer';
  160. }
  161. if (isset($db_secure)) {
  162. $this->configuration['database.0.secure'] = $db_secure;
  163. }
  164. if (isset($db_cert_authority)) {
  165. $this->configuration['database.0.cert_authority'] = $db_cert_authority;
  166. }
  167. //remove from the global namespace
  168. unset($db_type, $db_host, $db_port, $db_name, $db_username, $db_password, $db_sslmode, $db_secure, $db_cert_authority);
  169. }
  170. else {
  171. //save the loaded and parsed conf file to the object
  172. $this->configuration = parse_ini_file($this->file);
  173. }
  174. }
  175. // set project paths if not already defined
  176. private function define_project_paths() {
  177. // Load the document root
  178. $doc_root = $this->get('document.root', '/var/www/fusionpbx');
  179. $doc_path = $this->get('document.path', '');
  180. //set the server variables and define project path constant
  181. if (!empty($doc_path)) {
  182. if (!defined('PROJECT_PATH')) { define("PROJECT_PATH", $doc_path); }
  183. if (!defined('PROJECT_ROOT')) { define("PROJECT_ROOT", $doc_root.'/'.$doc_path); }
  184. }
  185. else {
  186. if (!defined('PROJECT_PATH')) { define("PROJECT_PATH", ''); }
  187. if (!defined('PROJECT_ROOT')) { define("PROJECT_ROOT", $doc_root); }
  188. }
  189. // internal definitions to the framework
  190. $_SERVER["PROJECT_PATH"] = PROJECT_PATH;
  191. $_SERVER["PROJECT_ROOT"] = PROJECT_ROOT;
  192. // tell php where the framework is
  193. $_SERVER["DOCUMENT_ROOT"] = PROJECT_ROOT;
  194. // have php search for any libraries in the now defined root
  195. set_include_path(PROJECT_ROOT);
  196. }
  197. /**
  198. * Find the path to the config.conf file
  199. * @var string $config_path - full path to the config.php file
  200. */
  201. public static function find(): string {
  202. //define the file variable
  203. $file = "";
  204. //find the file
  205. if (file_exists("/etc/fusionpbx/config.conf")) {
  206. $file = "/etc/fusionpbx/config.conf";
  207. }
  208. elseif (file_exists("/usr/local/etc/fusionpbx/config.conf")) {
  209. $file = "/usr/local/etc/fusionpbx/config.conf";
  210. }
  211. elseif (file_exists("/etc/fusionpbx/config.php")) {
  212. $file = "/etc/fusionpbx/config.php";
  213. }
  214. elseif (file_exists("/usr/local/etc/fusionpbx/config.php")) {
  215. $file = "/usr/local/etc/fusionpbx/config.php";
  216. }
  217. elseif (file_exists(getenv('SystemDrive') . DIRECTORY_SEPARATOR . 'ProgramData' . DIRECTORY_SEPARATOR . 'fusionpbx' . DIRECTORY_SEPARATOR . 'config.conf')) {
  218. $file = getenv('SystemDrive') . DIRECTORY_SEPARATOR . 'ProgramData' . DIRECTORY_SEPARATOR . 'fusionpbx' . DIRECTORY_SEPARATOR . 'config.conf';
  219. }
  220. elseif (file_exists(dirname(__DIR__, 2) . "/resources/config.php")) {
  221. //use the current web directory to find it as a last resort
  222. $file = "/var/www/fusionpbx/resources/config.php";
  223. }
  224. return $file;
  225. }
  226. /**
  227. * Get a configuration value using a key in the configuration file
  228. * @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
  229. * @param string $default_value if no matching key is found, then this value will be returned
  230. * @return string returns a value in the config.conf file or an empty string
  231. */
  232. public function get(string $key, string $default_value = ''): string {
  233. if (!empty($this->__get($key))) {
  234. return $this->__get($key);
  235. }
  236. return $default_value;
  237. }
  238. /**
  239. * Returns the config path or an empty string
  240. * @return string
  241. */
  242. public function path(): string {
  243. return dirname($this->file);
  244. }
  245. /**
  246. * Returns the file name only of the configuration file
  247. * @return string
  248. */
  249. public function filename(): string {
  250. return basename($this->file);
  251. }
  252. /**
  253. * Returns the path and the file name
  254. * @return string
  255. */
  256. public function path_and_filename(): string {
  257. return $this->file;
  258. }
  259. /**
  260. * Returns if the config class has a loaded configuration or not
  261. * @return bool True if configuration has loaded and false if it is empty
  262. */
  263. public function is_empty(): bool {
  264. return count($this->configuration) === 0;
  265. }
  266. /**
  267. * Returns the array of configuration settings
  268. * @return array
  269. */
  270. public function configuration(): array {
  271. return $this->configuration;
  272. }
  273. /**
  274. * Ensures the configuration file is loaded only once
  275. * @return config
  276. */
  277. public static function load(string $file = ''): config {
  278. if (self::$config === null) {
  279. self::$config = new config($file);
  280. }
  281. return self::$config;
  282. }
  283. }
  284. /*
  285. //Examples:
  286. //~~~~~~~~
  287. $config = new config;
  288. echo "Config path: " . $config->path() . "\n";
  289. echo "Config file: " . $config->filename() . "\n";
  290. echo "Full path and filename: " . $config->path_and_filename() . "\n";
  291. // show old style configuration options
  292. echo "db_type: ".$config->db_type."\n";
  293. echo "db_name: ".$config->db_name."\n";
  294. echo "db_username: ".$config->db_username."\n";
  295. echo "db_password: ".$config->db_password."\n";
  296. echo "db_host: ".$config->db_host."\n";
  297. echo "db_path: ".$config->db_path."\n";
  298. echo "db_port: ".$config->db_port."\n";
  299. // use current style configuration options even on old config.php
  300. echo "database.0.type: " . $config->get('database.0.type') . "\n";
  301. // use a default value
  302. echo "admin.name: " . $config->value('admin.name', 'admin') . "\n";
  303. // get all configuration options by printing the object
  304. echo "config settings: " . $config . "\n";
  305. // save the configuration options to a file
  306. file_put_contents('/etc/fusionpbx/config.conf', $config);
  307. // get all configuration options as an array
  308. var_dump($config->configuration());
  309. //*/