settings.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. <?php
  2. /**
  3. * settings class is used to load settings using hierarchical overriding
  4. *
  5. * The settings are loaded from the database tables default_settings, domain_settings, and user_settings in that order with
  6. * each setting overriding the setting from the previous table.
  7. *
  8. * @access public
  9. * @author Mark Crane <[email protected]>
  10. */
  11. class settings {
  12. /**
  13. * Set in the constructor. String used to load a specific domain. Must be a value domain UUID before sending to the constructor.
  14. * @var string
  15. */
  16. private $domain_uuid;
  17. /**
  18. * Set in the constructor. String used to load a specific user. Must be a valid user UUID before sending to the constructor.
  19. * @var string
  20. */
  21. private $user_uuid;
  22. /**
  23. * Set in the constructor. String used for loading a specific device UUID
  24. * @var string
  25. */
  26. private $device_uuid;
  27. /**
  28. * Set in the constructor. String used for loading device profile
  29. * @var string
  30. */
  31. private $device_profile_uuid;
  32. /**
  33. * Set in the constructor. Current category set to load
  34. * @var string
  35. */
  36. private $category;
  37. /**
  38. * Internal array structure that is populated from the database
  39. * @var array Array of settings loaded from Default Settings
  40. */
  41. private $settings;
  42. /**
  43. * Set in the constructor. Must be a database object and cannot be null.
  44. * @var database Database Object
  45. */
  46. private $database;
  47. /**
  48. * Create a settings object using key/value pairs in the $setting_array.
  49. *
  50. * Valid values are: database, domain_uuid, user_uuid, device_uuid, device_profile_uuid, and category.
  51. * @param array setting_array
  52. * @depends database::new()
  53. * @access public
  54. */
  55. public function __construct($setting_array = []) {
  56. //open a database connection
  57. if (empty($setting_array['database'])) {
  58. $this->database = database::new();
  59. } else {
  60. $this->database = $setting_array['database'];
  61. }
  62. //trap passing a PDO object instead of the required database object
  63. if (!($this->database instanceof database)) {
  64. //should never happen but will trap it here just-in-case
  65. throw new \InvalidArgumentException("Database object passed in settings class constructor is not a valid database object");
  66. }
  67. //set the values from the array
  68. $this->domain_uuid = $setting_array['domain_uuid'] ?? null;
  69. $this->user_uuid = $setting_array['user_uuid'] ?? null;
  70. $this->device_profile_uuid = $setting_array['device_profile_uuid'] ?? null;
  71. $this->device_uuid = $setting_array['device_uuid'] ?? null;
  72. $this->category = $setting_array['category'] ?? null;
  73. $this->reload();
  74. }
  75. /**
  76. * Returns the database object used in the settings
  77. * @return database Object
  78. */
  79. public function database(): database {
  80. return $this->database;
  81. }
  82. /**
  83. * Reloads the settings from the database
  84. */
  85. public function reload() {
  86. $this->settings = [];
  87. //set the default settings
  88. $this->default_settings();
  89. //set the domain settings
  90. if (!empty($this->domain_uuid)) {
  91. $this->domain_settings();
  92. //set the user settings only when the domain_uuid was set
  93. if (!empty($this->user_uuid)) {
  94. $this->user_settings();
  95. }
  96. //set the device profile settings
  97. if (!empty($this->device_profile_uuid)) {
  98. $this->device_profile_settings();
  99. }
  100. //set the device settings
  101. if (!empty($this->device_uuid)) {
  102. $this->device_settings();
  103. }
  104. }
  105. }
  106. /**
  107. * Get the value utilizing the hierarchical overriding technique
  108. * @param string $category Returns all settings when empty or the default value if the settings array is null
  109. * @param string $subcategory Returns the array of category items when empty or the default value if the category array is null
  110. * @param mixed $default_value allows default value returned if category and subcategory not found
  111. */
  112. public function get(string $category = null, string $subcategory = null, $default_value = null) {
  113. //incremental refinement from all settings to a single setting
  114. if (empty($category)) {
  115. return $this->settings ?? $default_value;
  116. }
  117. elseif (empty($subcategory)) {
  118. return $this->settings[$category] ?? $default_value;
  119. }
  120. else {
  121. return $this->settings[$category][$subcategory] ?? $default_value;
  122. }
  123. }
  124. /**
  125. * set the default, domain, user, device or device profile settings
  126. * @param string $table_prefix prefix for the table.
  127. * @param string $uuid uuid of the setting if available. If set to an empty string then a new uuid will be created.
  128. * @param string $category Category of the setting.
  129. * @param string $subcategory Subcategory of the setting.
  130. * @param string $type Type of the setting (array, numeric, text, etc)
  131. * @param string $value (optional) Value to set. Default is empty string.
  132. * @param bool $enabled (optional) True or False. Default is True.
  133. * @param string $description (optional) Description. Default is empty string.
  134. */
  135. public function set(string $table_prefix, string $uuid, string $category, string $subcategory, string $type = 'text', string $value = "", bool $enabled = true, string $description = "") {
  136. //set the table name
  137. $table_name = $table_prefix.'_settings';
  138. //init record as an array
  139. $record = [];
  140. if(!empty($this->domain_uuid)) {
  141. $record[$table_name][0]['domain_uuid'] = $this->domain_uuid;
  142. }
  143. if(!empty($this->user_uuid)) {
  144. $record[$table_name][0]['user_uuid'] = $this->user_uuid;
  145. }
  146. if(!empty($this->device_uuid)) {
  147. $record[$table_name][0]['device_uuid'] = $this->device_uuid;
  148. }
  149. if(!empty($this->device_profile_uuid)) {
  150. $record[$table_name][0]['device_profile_uuid'] = $this->device_profile_uuid;
  151. }
  152. if(!is_uuid($uuid)) {
  153. $uuid = uuid();
  154. }
  155. //build the array
  156. $record[$table_name][0][$table_prefix.'_setting_uuid' ] = $uuid;
  157. $record[$table_name][0][$table_prefix.'_setting_category' ] = $category;
  158. $record[$table_name][0][$table_prefix.'_setting_subcategory'] = $subcategory;
  159. $record[$table_name][0][$table_prefix.'_setting_name' ] = $type;
  160. $record[$table_name][0][$table_prefix.'_setting_value' ] = $value;
  161. $record[$table_name][0][$table_prefix.'_setting_enabled' ] = $enabled;
  162. $record[$table_name][0][$table_prefix.'_setting_description'] = $description;
  163. //grant temporary permissions
  164. $p = permissions::new();
  165. $p->add($table_prefix.'_setting_add', 'temp');
  166. $p->add($table_prefix.'_setting_edit', 'temp');
  167. //execute insert
  168. $this->database->app_name = $table_name;
  169. $this->database->save($record);
  170. //revoke temporary permissions
  171. $p->delete($table_prefix.'_setting_add', 'temp');
  172. $p->delete($table_prefix.'_setting_edit', 'temp');
  173. }
  174. /**
  175. * Update the internal settings array with the default settings from the database
  176. * @access private
  177. */
  178. private function default_settings() {
  179. //get the default settings
  180. $sql = "select * from v_default_settings ";
  181. $sql .= "where default_setting_enabled = 'true' ";
  182. if (!empty($this->category)) {
  183. $sql .= "and default_setting_category = :default_setting_category ";
  184. $parameters['default_setting_category'] = $this->category;
  185. }
  186. $sql .= "order by default_setting_order asc ";
  187. $result = $this->database->select($sql, $parameters ?? null, 'all');
  188. if (!empty($result)) {
  189. foreach ($result as $row) {
  190. $name = $row['default_setting_name'];
  191. $category = $row['default_setting_category'];
  192. $subcategory = $row['default_setting_subcategory'];
  193. if (isset($row['default_setting_value']) && $row['default_setting_value'] !== '') {
  194. if ($name == "boolean") {
  195. if (gettype($row['default_setting_value']) === 'string') {
  196. if ($row['default_setting_value'] === 'true') {
  197. $this->settings[$category][$subcategory] = true;
  198. }
  199. else {
  200. $this->settings[$category][$subcategory] = false;
  201. }
  202. }
  203. elseif (gettype($row['default_setting_value']) === 'boolean') {
  204. $this->settings[$category][$subcategory] = $row['default_setting_value'];
  205. }
  206. }
  207. elseif ($name == "array") {
  208. if (!isset($this->settings[$category][$subcategory]) || !is_array($this->settings[$category][$subcategory])) {
  209. $this->settings[$category][$subcategory] = array();
  210. }
  211. $this->settings[$category][$subcategory][] = $row['default_setting_value'];
  212. }
  213. else {
  214. $this->settings[$category][$subcategory] = $row['default_setting_value'];
  215. }
  216. }
  217. }
  218. }
  219. unset($sql, $result, $row);
  220. }
  221. /**
  222. * Update the internal settings array with the domain settings from the database
  223. * @access private
  224. */
  225. private function domain_settings() {
  226. $sql = "select * from v_domain_settings ";
  227. $sql .= "where domain_uuid = :domain_uuid ";
  228. $sql .= "and domain_setting_enabled = 'true' ";
  229. $parameters['domain_uuid'] = $this->domain_uuid;
  230. $result = $this->database->select($sql, $parameters, 'all');
  231. unset($sql, $parameters);
  232. if (!empty($result)) {
  233. //domain setting array types override the default settings set as type array
  234. foreach ($result as $row) {
  235. $name = $row['domain_setting_name'];
  236. $category = $row['domain_setting_category'];
  237. $subcategory = $row['domain_setting_subcategory'];
  238. if ($name == "array") {
  239. $this->settings[$category][$subcategory] = array();
  240. }
  241. }
  242. //add the domain settings to the $this->settings array
  243. foreach ($result as $row) {
  244. $name = $row['domain_setting_name'];
  245. $category = $row['domain_setting_category'];
  246. $subcategory = $row['domain_setting_subcategory'];
  247. if (isset($row['domain_setting_value']) && $row['domain_setting_value'] !== '') {
  248. if ($name == "boolean") {
  249. if (gettype($row['domain_setting_value']) === 'string') {
  250. if ($row['domain_setting_value'] === 'true') {
  251. $this->settings[$category][$subcategory] = true;
  252. }
  253. else {
  254. $this->settings[$category][$subcategory] = false;
  255. }
  256. }
  257. elseif (gettype($row['domain_setting_value']) === 'boolean') {
  258. $this->settings[$category][$subcategory] = $row['domain_setting_value'];
  259. }
  260. }
  261. if ($name == "array") {
  262. if (!isset($this->settings[$category][$subcategory]) || !is_array($this->settings[$category][$subcategory])) {
  263. $this->settings[$category][$subcategory] = array();
  264. }
  265. $this->settings[$category][$subcategory][] = $row['domain_setting_value'];
  266. }
  267. else {
  268. $this->settings[$category][$subcategory] = $row['domain_setting_value'];
  269. }
  270. }
  271. }
  272. }
  273. unset($result, $row);
  274. }
  275. /**
  276. * Update the internal settings array with the user settings from the database
  277. * @access private
  278. * @depends $this->domain_uuid
  279. */
  280. private function user_settings() {
  281. $sql = "select * from v_user_settings ";
  282. $sql .= "where domain_uuid = :domain_uuid ";
  283. $sql .= "and user_uuid = :user_uuid ";
  284. $sql .= " order by user_setting_order asc ";
  285. $parameters['domain_uuid'] = $this->domain_uuid;
  286. $parameters['user_uuid'] = $this->user_uuid;
  287. $result = $this->database->select($sql, $parameters, 'all');
  288. if (is_array($result)) {
  289. foreach ($result as $row) {
  290. if ($row['user_setting_enabled'] == 'true') {
  291. $name = $row['user_setting_name'];
  292. $category = $row['user_setting_category'];
  293. $subcategory = $row['user_setting_subcategory'];
  294. if (isset($row['user_setting_value']) && $row['user_setting_value'] !== '') {
  295. if ($name == "boolean") {
  296. if (gettype($row['user_setting_value']) === 'string') {
  297. if ($row['user_setting_value'] === 'true') {
  298. $this->settings[$category][$subcategory] = true;
  299. }
  300. else {
  301. $this->settings[$category][$subcategory] = false;
  302. }
  303. }
  304. elseif (gettype($row['user_setting_value']) === 'boolean') {
  305. $this->settings[$category][$subcategory] = $row['user_setting_value'];
  306. }
  307. }
  308. elseif ($name == "array") {
  309. $this->settings[$category][$subcategory][] = $row['user_setting_value'];
  310. }
  311. else {
  312. $this->settings[$category][$subcategory] = $row['user_setting_value'];
  313. }
  314. }
  315. }
  316. }
  317. }
  318. }
  319. /**
  320. * Update the internal settings array with the device profile settings from the database
  321. * @access private
  322. * @depends $this->domain_uuid
  323. */
  324. private function device_profile_settings() {
  325. //get the device profile settings
  326. $sql = "select profile_setting_name, profile_setting_value from v_device_profile_settings"
  327. . " where device_profile_uuid = :device_profile_uuid"
  328. . " and domain_uuid = :domain_uuid"
  329. . " and profile_setting_enabled = 'true'"
  330. ;
  331. $params = [];
  332. $params['device_profile_uuid'] = $this->device_profile_uuid;
  333. $params['domain_uuid'] = $this->domain_uuid;
  334. $result = $this->database->select($sql, $params, 'all');
  335. if (!empty($result)) {
  336. foreach ($result as $row) {
  337. $name = $row['profile_setting_name'];
  338. $value = $row['profile_setting_value'];
  339. $this->settings[$name] = $value;
  340. }
  341. }
  342. }
  343. /**
  344. * Update the internal settings array with the device settings from the database
  345. * @access private
  346. * @depends $this->domain_uuid
  347. */
  348. private function device_settings() {
  349. //get the device settings
  350. $sql = "select device_setting_subcategory, device_setting_value from v_device_settings"
  351. . " where device_setting_uuid = :device_uuid"
  352. . " and domain_uuid = :domain_uuid"
  353. . " and device_setting_enabled = 'true'"
  354. ;
  355. $params = [];
  356. $params['device_uuid'] = $this->device_uuid;
  357. $params['domain_uuid'] = $this->domain_uuid;
  358. $result = $this->database->select($sql, $params, 'all');
  359. if (!empty($result)) {
  360. foreach ($result as $row) {
  361. $name = $row['device_setting_subcategory'];
  362. $value = $row['device_setting_value'] ?? null;
  363. $this->settings[$name] = $value;
  364. }
  365. }
  366. }
  367. }