1<?php
2
3/**
4 * This file is part of the Froxlor project.
5 * Copyright (c) 2010 the Froxlor Team (see authors).
6 *
7 * For the full copyright and license information, please view the COPYING
8 * file that was distributed with this source code. You can also view the
9 * COPYING file online at http://files.froxlor.org/misc/COPYING.txt
10 *
11 * @copyright  (c) the authors
12 * @author     Michael Kaufmann <mkaufmann@nutime.de>
13 * @author     Froxlor team <team@froxlor.org> (2010-)
14 * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
15 * @package    Classes
16 *
17 * @since      0.9.31
18 *
19 */
20
21/**
22 * Class Settings
23 *
24 * Interaction with settings from the db
25 *
26 * @copyright  (c) the authors
27 * @author     Michael Kaufmann <mkaufmann@nutime.de>
28 * @author     Froxlor team <team@froxlor.org> (2010-)
29 * @license    GPLv2 http://files.froxlor.org/misc/COPYING.txt
30 * @package    Classes
31 */
32class Settings {
33
34	/**
35	 * current settings object
36	 *
37	 * @var object
38	 */
39	private static $_obj = null;
40
41	/**
42	 * settings data
43	 *
44	 * @var array
45	 */
46	private static $_data = null;
47
48	/**
49	 * changed and unsaved settings data
50	 *
51	 * @var array
52	 */
53	private static $_updatedata = null;
54
55	/**
56	 * prepared statement for updating the
57	 * settings table
58	 *
59	 * @var PDOStatement
60	 */
61	private static $_updstmt = null;
62
63	/**
64	 * private constructor, reads in all settings
65	 */
66	private function __construct() {
67		$this->_readSettings();
68		self::$_updatedata = array();
69		// prepare statement
70		self::$_updstmt = Database::prepare("
71				UPDATE `".TABLE_PANEL_SETTINGS."` SET `value` = :value
72				WHERE `settinggroup` = :group AND `varname` = :varname
73				");
74	}
75
76	/**
77	 * Read in all settings from the database
78	 * and set the internal $_data array
79	 */
80	private function _readSettings() {
81		$result_stmt = Database::query("
82				SELECT `settingid`, `settinggroup`, `varname`, `value`
83				FROM `" . TABLE_PANEL_SETTINGS . "`
84				");
85		self::$_data = array();
86		while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
87			self::$_data[$row['settinggroup']][$row['varname']] = $row['value'];
88		}
89		return true;
90	}
91
92	/**
93	 * update a value in the database
94	 *
95	 * @param string $group
96	 * @param string $varname
97	 * @param string $value
98	 */
99	private function _storeSetting($group = null, $varname = null, $value = null) {
100		$upd_data = array(
101				'group' => $group,
102				'varname' => $varname,
103				'value' => $value
104		);
105		Database::pexecute(self::$_updstmt, $upd_data);
106	}
107
108	/**
109	 * return a setting-value by its group and varname
110	 *
111	 * @param string $setting a group and a varname separated by a dot (group.varname)
112	 *
113	 * @return mixed
114	 */
115	public function pGet($setting = null) {
116		$sstr = explode(".", $setting);
117		// no separator - do'h
118		if (!isset($sstr[1])) {
119			return null;
120		}
121		$result = null;
122		if (isset(self::$_data[$sstr[0]][$sstr[1]])) {
123			$result = self::$_data[$sstr[0]][$sstr[1]];
124		}
125		return $result;
126	}
127
128	/**
129	 * tests if a setting-value that i s a comma separated list contains an entry
130	 *
131	 * @param string $setting a group and a varname separated by a dot (group.varname)
132	 * @param string $entry the entry that is expected to be in the list
133	 *
134	 * @return boolean true, if the list contains $entry
135	 */
136	public function pIsInList($setting = null, $entry = null) {
137		$s=Settings::Get($setting);
138		if ($s==null) {
139			return false;
140		}
141		$slist = explode(",",$s);
142		return in_array($entry, $slist);
143	}
144
145	/**
146	 * update a setting / set a new value
147	 *
148	 * @param string $setting a group and a varname separated by a dot (group.varname)
149	 * @param string $value
150	 * @param boolean $instant_save
151	 */
152	public function pSet($setting = null, $value = null, $instant_save = true) {
153		// check whether the setting exists
154		if (Settings::Get($setting) !== null) {
155			// set new value in array
156			$sstr = explode(".", $setting);
157			if (!isset($sstr[1])) {
158				return false;
159			}
160			self::$_data[$sstr[0]][$sstr[1]] = $value;
161			// should we store to db instantly?
162			if ($instant_save) {
163				$this->_storeSetting($sstr[0], $sstr[1], $value);
164			} else {
165				// set temporary data for usage
166				if (!isset(self::$_data[$sstr[0]]) || !is_array(self::$_data[$sstr[0]])) {
167					self::$_data[$sstr[0]] = array();
168				}
169				self::$_data[$sstr[0]][$sstr[1]] = $value;
170				// set update-data when invoking Flush()
171				if (!isset(self::$_updatedata[$sstr[0]]) || !is_array(self::$_updatedata[$sstr[0]])) {
172					self::$_updatedata[$sstr[0]] = array();
173				}
174				self::$_updatedata[$sstr[0]][$sstr[1]] = $value;
175			}
176			return true;
177		}
178		return false;
179	}
180
181	/**
182	 * add a new setting to the database (mainly used in updater)
183	 *
184	 * @param string $setting a group and a varname separated by a dot (group.varname)
185	 * @param string $value
186	 *
187	 * @return boolean
188	 */
189	public function pAddNew($setting = null, $value = null) {
190
191		// first check if it doesn't exist
192		if (Settings::Get($setting) === null) {
193			// validate parameter
194			$sstr = explode(".", $setting);
195			if (!isset($sstr[1])) {
196				return false;
197			}
198			// prepare statement
199			$ins_stmt = Database::prepare("
200					INSERT INTO `".TABLE_PANEL_SETTINGS."` SET
201					`settinggroup` = :group,
202					`varname` = :varname,
203					`value` = :value
204					");
205			$ins_data = array(
206					'group' => $sstr[0],
207					'varname' => $sstr[1],
208					'value' => $value
209			);
210			Database::pexecute($ins_stmt, $ins_data);
211			// also set new value to internal array and make it available
212			self::$_data[$sstr[0]][$sstr[1]] = $value;
213			return true;
214		}
215		return false;
216	}
217
218	/**
219	 * Store all un-saved changes to the database and
220	 * re-read in all settings
221	 */
222	public function pFlush() {
223		if (is_array(self::$_updatedata) && count(self::$_updatedata) > 0) {
224			// save all un-saved changes to the settings
225			foreach (self::$_updatedata as $group => $vargroup) {
226				foreach ($vargroup as $varname => $value) {
227					$this->_storeSetting($group, $varname, $value);
228				}
229			}
230			// now empty the array
231			self::$_updatedata = array();
232			// re-read in all settings
233			return $this->_readSettings();
234		}
235		return false;
236	}
237
238	/**
239	 * forget all un-saved changes to settings
240	 */
241	public function pStash() {
242		// empty update array
243		self::$_updatedata = array();
244	}
245
246	/**
247	 * create new object and return instance
248	 *
249	 * @return object
250	 */
251	private static function getInstance() {
252		// do we got an object already?
253		if (self::$_obj == null) {
254			self::$_obj = new self();
255		}
256		// return it
257		return self::$_obj;
258	}
259
260	/**
261	 * let's us interact with the settings-Object by using static
262	 * call like "Settings::function()"
263	 *
264	 * @param string $name
265	 * @param mixed $args
266	 *
267	 * @return mixed
268	 */
269	public static function __callStatic($name, $args) {
270		// as our functions are not static and therefore cannot
271		// be called statically, we prefix a 'p' to all of
272		// our public functions so we can use Settings::functionname()
273		// which looks cooler and is easier to use
274		$callback = array(self::getInstance(), "p".$name);
275		$result = call_user_func_array($callback, $args);
276		return $result;
277	}
278}
279