1<?php
2/*
3 * e107 website system
4 *
5 * Copyright (C) 2008-2010 e107 Inc (e107.org)
6 * Released under the terms and conditions of the
7 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
8 *
9 * e107 Preference Handler
10 *
11 * $URL$
12 * $Id$
13*/
14
15if (!defined('e107_INIT')) { exit; }
16require_once(e_HANDLER.'model_class.php');
17
18/**
19 * Base preference object - shouldn't be used direct,
20 * used internal by {@link e_plugin_pref} and {@link e_core_pref classes}
21 *
22 * @package e107
23 * @category e107_handlers
24 * @version $Id$
25 * @author SecretR
26 * @copyright Copyright (c) 2009, e107 Inc.
27 */
28class e_pref extends e_front_model
29{
30	/**
31	 * Preference ID - DB row value
32	 *
33	 * @var string
34	 */
35	protected $prefid;
36
37	/**
38	 * Preference ID alias e.g. 'core' is an alias of prefid 'SitePrefs'
39	 * Used in e.g. server cache file name
40	 *
41	 * @var string
42	 */
43	protected $alias;
44
45	/**
46	 * Runtime cache, set on first data load
47	 *
48	 * @var string
49	 */
50	protected $pref_cache = '';
51
52	/**
53	 * Backward compatibility - serialized preferences
54	 * Note: serialized preference storage is deprecated
55	 *
56	 * @var boolean
57	 */
58	protected $serial_bc = false;
59
60	/**
61	 * If true, $prefid.'_Backup' row will be created/updated
62	 * on every {@link save()} call
63	 *
64	 * @var boolean
65	 */
66	protected $set_backup = false;
67
68	/**
69	 * Constructor
70	 *
71	 * @param string $prefid
72	 * @param string $alias Used by cache file.
73	 * @param array $data
74	 * @param boolean $sanitize_data
75	 */
76	function __construct($prefid, $alias = '', $data = array(), $sanitize_data = true)
77	{
78		require_once(e_HANDLER.'cache_handler.php');
79
80		$this->prefid = preg_replace('/[^\w\-]/', '', $prefid);
81
82		if(empty($alias))
83		{
84			$alias = $prefid;
85		}
86
87		$this->alias = preg_replace('/[^\w\-]/', '', $alias);
88
89		$this->loadData($data, $sanitize_data);
90	}
91
92	/**
93	 * Advanced getter - $pref_name could be path in format 'pref1/pref2/pref3' (multidimensional arrays support),
94	 * alias of {@link e_model::getData()}
95	 * If $pref_name is empty, all data array will be returned
96	 *
97	 * @param string $pref_name
98	 * @param mixed $default
99	 * @param integer $index
100	 * @return mixed
101	 */
102	public function getPref($pref_name = '', $default = null, $index = null)
103	{
104		return $this->getData($pref_name, $default, $index);
105	}
106
107	/**
108	 * Simple getter - $pref_name is not parsed (no multidimensional arrays support), alias of {@link e_model::get()}
109	 * This is the prefered (performance wise) method when simple preference is retrieved
110	 *
111	 * @param string $pref_name
112	 * @param mixed $default
113	 * @return mixed
114	 */
115	public function get($pref_name, $default = null)
116	{
117		return parent::get((string) $pref_name, $default);
118	}
119
120	/**
121	 * Advanced setter - $pref_name could be path in format 'pref1/pref2/pref3' (multidimensional arrays support)
122	 * If $pref_name is array, it'll be merged with existing preference data, non existing preferences will be added as well
123	 *
124	 * @param string|array $pref_name
125	 * @param mixed $value
126	 * @return e_pref
127	 */
128	public function setPref($pref_name, $value = null)
129	{
130		global $pref;
131		//object reset not allowed, adding new pref is allowed
132		if(empty($pref_name))
133		{
134			return $this;
135		}
136
137		//Merge only allowed
138		if(is_array($pref_name))
139		{
140			$this->mergeData($pref_name, false, false, false);
141			return $this;
142		}
143
144		parent::setData($pref_name, $value, false);
145
146		//BC
147		if($this->alias === 'core')
148		{
149			$pref = $this->getData();
150		}
151		return $this;
152	}
153
154    /**
155     * Reset preference object to given/empty state
156     * @param array $prefs
157     * @return $this
158     */
159    public function reset($prefs = array())
160    {
161        parent::setData(array());
162
163        return $this;
164    }
165
166	/**
167	 * Advanced setter - $pref_name could be path in format 'pref1/pref2/pref3' (multidimensional arrays support)
168	 * Object data reseting is not allowed, adding new preferences is controlled by $strict parameter
169	 *
170	 * @param string|array $pref_name
171	 * @param mixed $value
172	 * @param boolean $strict true - update only, false - same as setPref()
173	 * @return e_pref
174	 */
175	public function updatePref($pref_name, $value = null, $strict = false)
176	{
177		global $pref;
178		//object reset not allowed, adding new pref is not allowed
179		if(empty($pref_name))
180		{
181			return $this;
182		}
183
184		//Merge only allowed
185		if(is_array($pref_name))
186		{
187			$this->mergeData($pref_name, $strict, false, false);
188			return $this;
189		}
190
191		parent::setData($pref_name, $value, $strict);
192
193		//BC
194		if($this->alias === 'core')
195		{
196			$pref = $this->getData();
197		}
198		return $this;
199	}
200
201	/**
202	 * Simple setter - $pref_name is not parsed (no multidimensional arrays support)
203	 * Adding new pref is allowed
204	 *
205	 * @param string $pref_name
206	 * @param mixed $value
207	 * @return e_pref
208	 */
209	public function set($pref_name, $value=null, $strict = false)
210	{
211		global $pref;
212		if(empty($pref_name) || !is_string($pref_name))
213		{
214			return $this;
215		}
216
217		if(!isset($this->_data[$pref_name]) || $this->_data[$pref_name] != $value) $this->data_has_changed = true;
218		$this->_data[$pref_name] = $value;
219
220		//BC
221		if($this->alias === 'core')
222		{
223			$pref = $this->getData();
224		}
225		return $this;
226	}
227
228	/**
229	 * Simple setter - $pref_name is  not parsed (no multidimensional arrays support)
230	 * Non existing setting will be not created
231	 *
232	 * @param string $pref_name
233	 * @param mixed $value
234	 * @return e_pref
235	 */
236	public function update($pref_name, $value)
237	{
238		global $pref;
239		if(empty($pref_name) || !is_string($pref_name))
240		{
241			return $this;
242		}
243		if(array_key_exists($pref_name, $this->_data))
244		{
245			if($this->_data[$pref_name] != $value) $this->data_has_changed = true;
246			$this->_data[$pref_name] = $value;
247		}
248
249		//BC
250		if($this->alias === 'core')
251		{
252			$pref = $this->getData();
253		}
254		return $this;
255	}
256
257	/**
258	 * Add new (single) preference (ONLY if doesn't exist)
259	 * No multidimensional arrays support
260	 *
261	 * @see addData()
262	 * @param string $pref_name
263	 * @param mixed $value
264	 * @return e_pref
265	 */
266	public function add($pref_name, $value)
267	{
268		if(empty($pref_name) || !is_string($pref_name))
269		{
270			return $this;
271		}
272		if(!isset($this->_data[$pref_name]))
273		{
274			$this->_data[$pref_name] = $value;
275			$this->data_has_changed = true;
276		}
277
278		//BC
279		if($this->alias === 'core')
280		{
281			$pref = $this->getData();
282		}
283		return $this;
284	}
285
286	/**
287	 * Add new preference or preference array (ONLY if it/they doesn't exist)
288	 * $pref_name could be path in format 'pref1/pref2/pref3'
289	 *
290	 * @see addData()
291	 * @param string|array $pref_name
292	 * @param mixed $value
293	 * @return e_pref
294	 */
295	public function addPref($pref_name, $value = null)
296	{
297		$this->addData($pref_name, $value);
298		return $this;
299	}
300
301	/**
302	 * Remove single preference
303	 * $pref_name is not parsed as a path
304	 *
305	 * @see e_model::remove()
306	 * @param string $pref_name
307	 * @return e_pref
308	 */
309	public function remove($pref_name)
310	{
311		global $pref;
312		parent::remove((string) $pref_name);
313
314		//BC
315		if($this->alias === 'core')
316		{
317			$pref = $this->getData();
318		}
319		return $this;
320	}
321
322	/**
323	 * Remove single preference (parse $pref_name)
324	 * $pref_name could be path in format 'pref1/pref2/pref3'
325	 *
326	 * @see removeData()
327	 * @param string $pref_name
328	 * @return e_pref
329	 */
330	public function removePref($pref_name)
331	{
332		$this->removeData($pref_name);
333		return $this;
334	}
335
336	/**
337	 * Disallow public use of e_model::addData()
338	 * Disallow preference override
339	 *
340	 * @param string|array $pref_name
341	 * @param mixed value
342	 * @param boolean $strict
343	 * @return $this|\e_model
344	 */
345	final public function addData($pref_name, $value = null, $override = true)
346	{
347		global $pref;
348		parent::addData($pref_name, $value, false);
349		//BC
350		if($this->alias === 'core')
351		{
352			$pref = $this->getData();
353		}
354		return $this;
355	}
356
357	/**
358	 * Disallow public use of e_model::setData()
359	 * Only data merge possible
360	 *
361	 * @param string|array $pref_name
362	 * @param mixed $value
363	 * @return e_pref
364	 */
365	final public function setData($pref_name, $value = null, $strict = false)
366	{
367		global $pref;
368		if(empty($pref_name))
369		{
370			return $this;
371		}
372
373		//Merge only allowed
374		if(is_array($pref_name))
375		{
376			$this->mergeData($pref_name, false, false, false);
377			return $this;
378		}
379
380		parent::setData($pref_name, $value, false);
381
382		//BC
383		if($this->alias === 'core')
384		{
385			$pref = $this->getData();
386		}
387		return $this;
388	}
389
390	/**
391	 * Disallow public use of e_model::removeData()
392	 * Object data reseting is not allowed
393	 *
394	 * @param string $pref_name
395	 * @return e_pref
396	 */
397	final public function removeData($pref_name=null)
398	{
399		global $pref;
400		parent::removeData((string) $pref_name);
401
402		//BC
403		if($this->alias === 'core')
404		{
405			$pref = $this->getData();
406		}
407		return $this;
408	}
409
410	/**
411	 * Reset object data
412	 *
413	 * @param array $data
414	 * @param boolean $sanitize
415	 * @return e_pref
416	 */
417	public function loadData(array $data, $sanitize = true)
418	{
419		global $pref;
420		if(!empty($data))
421		{
422			if($sanitize)
423			{
424				$data = e107::getParser()->toDB($data);
425			}
426			parent::setData($data, null, false);
427			$this->pref_cache = e107::getArrayStorage()->WriteArray($data, false); //runtime cache
428			//BC
429			if($this->alias === 'core')
430			{
431				$pref = $this->getData();
432			}
433		}
434		return $this;
435	}
436
437	/**
438	 * Load object data - public
439	 *
440	 * @see _load()
441	 * @param boolean $force
442	 * @return e_pref
443	 */
444	public function load($id=null, $force = false)
445	{
446		global $pref;
447		if($force || !$this->hasData())
448		{
449			$this->data_has_changed = false;
450			$this->_load($force);
451			//BC
452			if($this->alias === 'core')
453			{
454				$pref = $this->getData();
455			}
456		}
457
458		return $this;
459	}
460
461	/**
462	 * Load object data
463	 *
464	 * @param boolean $force
465	 * @return e_pref
466	 */
467	protected function _load($force = false)
468	{
469		$id = $this->prefid;
470		$data = $force ? false : $this->getPrefCache(true);
471
472		if(!empty($data))
473		{
474			$this->pref_cache = e107::getArrayStorage()->WriteArray($data, false); //runtime cache
475			$this->loadData((array) $data, false);
476			return $this;
477		}
478
479		if (e107::getDb()->select('core', 'e107_value', "e107_name='{$id}'"))
480		{
481			$row = e107::getDb()->fetch();
482
483			if($this->serial_bc)
484			{
485				$data = unserialize($row['e107_value']);
486				$row['e107_value'] = e107::getArrayStorage()->WriteArray($data, false);
487			}
488			else
489			{
490				$data = e107::unserialize($row['e107_value']);
491			}
492
493			$this->pref_cache = $row['e107_value']; //runtime cache
494			$this->setPrefCache($row['e107_value'], true);
495		}
496
497		if(empty($data))
498			$data = array();
499
500		$this->loadData($data, false);
501		return $this;
502	}
503
504	/**
505	 * Save object data to DB
506	 *
507	 * @param boolean $from_post merge post data
508	 * @param boolean $force
509	 * @param mixed $session_messages      null: normal messages displayed, true: session messages used, false: no messages displayed.
510	 * @return boolean|integer 0 - no change, true - saved, false - error
511	 */
512	public function save($from_post = true, $force = false, $session_messages = null)
513	{
514		global $pref;
515		if(!$this->prefid)
516		{
517			return false;
518		}
519
520		e107::getMessage()->setUnique($this->prefid); // attempt to fix
521
522		if($from_post)
523		{
524			$this->mergePostedData(); //all posted data is sanitized and filtered vs preferences/_data_fields array
525		}
526
527		if($this->hasValidationError())
528		{
529			return false;
530		}
531
532		if(!$this->data_has_changed && !$force)
533		{
534			if($session_messages !== false)
535			{
536				e107::getMessage()->addInfo(LAN_SETTINGS_NOT_SAVED_NO_CHANGES_MADE, $this->prefid, $session_messages)->moveStack($this->prefid);
537			}
538
539			return 0;
540		}
541
542		$log = e107::getAdminLog();
543		$disallow_logs = $this->getParam('nologs', false);
544
545		//Save to DB
546		if(!$this->hasError())
547		{
548			if($this->serial_bc)
549			{
550				$dbdata = serialize($this->getPref());
551			}
552			else
553			{
554				$dbdata = $this->toString(false);
555			}
556
557			if(e107::getDb()->gen("REPLACE INTO `#core` (e107_name,e107_value) values ('{$this->prefid}', '".addslashes($dbdata)."') "))
558			{
559				$this->data_has_changed = false; //reset status
560
561				if(!empty($this->pref_cache))
562				{
563					$old = e107::unserialize($this->pref_cache);
564					if($this->serial_bc)
565					{
566						$dbdata = serialize($old);
567					}
568					else
569					{
570						$dbdata = $this->pref_cache;
571					}
572
573					// auto admin log
574					if(is_array($old) && !$disallow_logs) // fix install problems - no old prefs available
575					{
576						$new = $this->getPref();
577					//	$log->logArrayDiffs($new, $old, 'PREFS_02', false);
578						$log->addArray($new,$old);
579						unset($new, $old);
580
581					}
582
583					// Backup
584					if($this->set_backup === true && e107::getDb()->gen("REPLACE INTO `#core` (e107_name,e107_value) values ('".$this->prefid."_Backup', '".addslashes($dbdata)."') "))
585					{
586						if(!$disallow_logs) $log->logMessage('Backup of <strong>'.$this->alias.' ('.$this->prefid.')</strong> successfully created.', E_MESSAGE_DEBUG, E_MESSAGE_SUCCESS, $session_messages);
587						e107::getCache()->clear_sys('Config_'.$this->alias.'_backup');
588						if(deftrue('e_DEBUG'))
589						{
590							$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,2);
591							$log->logMessage(print_a($backtrace,true),  E_MESSAGE_DEBUG);
592						}
593					}
594
595				}
596
597				$this->setPrefCache($this->toString(false), true); //reset pref cache - runtime & file
598
599				if($this->alias == 'search') // Quick Fix TODO Improve.
600				{
601					$logId = 'SEARCH_04';
602				}
603				elseif($this->alias == 'notify')
604				{
605					$logId = 'NOTIFY_01';
606				}
607				else
608				{
609					$logId = 'PREFS_01';
610				}
611
612				// FIXME: Admin LAN dependency out of nowhere
613				e107::includeLan(e_LANGUAGEDIR . e_LANGUAGE . '/admin/lan_admin.php');
614
615				$log->addSuccess(LAN_SETSAVED, ($session_messages === null || $session_messages === true));
616
617				$uid = USERID;
618
619				if(empty($uid)) // Log extra details of any pref changes made by a non-user.
620				{
621					$log->addWarning(print_r(debug_backtrace(null,2), true), false);
622				}
623
624				$log->save($logId);
625
626			//	if(!$disallow_logs) $log->logSuccess('Settings successfully saved.', true, $session_messages)->flushMessages($logId, E_LOG_INFORMATIVE, '', $this->prefid);
627
628
629				//BC
630				if($this->alias === 'core')
631				{
632					$pref = $this->getPref();
633				}
634				e107::getMessage()->moveStack($this->prefid);
635				return true;
636			}
637			elseif(e107::getDb()->getLastErrorNumber())
638			{
639				if(!$disallow_logs)
640					$log->logError('mySQL error #'.e107::getDb()->getLastErrorNumber().': '.e107::getDb()->getLastErrorText(), true, $session_messages)
641					->logError('Settings not saved.', true, $session_messages)
642					->flushMessages('PREFS_03', E_LOG_INFORMATIVE, '', $this->prefid);
643
644				e107::getMessage()->moveStack($this->prefid);
645				return false;
646			}
647		}
648
649		if($this->hasError())
650		{
651			//add errors to the eMessage stack
652			//$this->setErrors(true, $session_messages); old - doesn't needed anymore
653			if(!$disallow_logs)
654				$log->logError('Settings not saved.', true, $session_messages)
655				->flushMessages('LAN_FIXME', E_LOG_INFORMATIVE, '', $this->prefid);
656
657			e107::getMessage()->moveStack($this->prefid);
658			return false;
659		}
660		else
661		{
662			e107::getMessage()->addInfo(LAN_SETTINGS_NOT_SAVED_NO_CHANGES_MADE, $this->prefid, $session_messages);
663			if(!$disallow_logs) $log->flushMessages('LAN_FIXME', E_LOG_INFORMATIVE, '', $this->prefid);
664			e107::getMessage()->moveStack($this->prefid);
665			return 0;
666		}
667	}
668
669	/**
670	 * Get cached data from server cache file
671	 *
672	 * @param boolean $toArray convert to array
673	 * @return string|array|false
674	 */
675	protected function getPrefCache($toArray = true)
676	{
677		if(!$this->pref_cache)
678		{
679			$this->pref_cache = e107::getCache()->retrieve_sys('Config_'.$this->alias, 24 * 60, true);
680		}
681
682		return ($toArray && $this->pref_cache ? e107::unserialize($this->pref_cache) : $this->pref_cache);
683	}
684
685	/**
686	 * Convert data to a string and store it to a server cache file
687	 * If $cache_string is an array, it'll be converted to a string
688	 * If $save is string, it'll be used for building the cache filename
689	 *
690	 * @param string|array $cache_string
691	 * @param string|boolean $save write to a file
692	 * @return e_pref
693	 */
694	protected function setPrefCache($cache_string, $save = false)
695	{
696		if(is_array($cache_string))
697		{
698			$cache_string = e107::getArrayStorage()->WriteArray($cache_string, false);
699		}
700		if(is_bool($save))
701		{
702			$this->pref_cache = $cache_string;
703		}
704		if($save)
705		{
706			e107::getCache()->set_sys('Config_'.($save !== true ? $save : $this->alias), $cache_string, true);
707		}
708		return $this;
709	}
710
711	/**
712	 * Clear pref cache
713	 *
714	 * @param string $cache_name default to current alias
715	 * @param boolean $runtime clear runtime cache as well ($this->pref_cache)
716	 * @return e_pref
717	 */
718	public function clearPrefCache($cache_name = '', $runtime = true)
719	{
720		if($runtime)
721		{
722			$this->pref_cache = '';
723		}
724		e107::getCache()->clear_sys('Config_'.(!empty($cache_name) ? $cache_name : $this->alias));
725		return $this;
726	}
727
728	/**
729	 * Validation
730	 *
731	 * @param array $data [optional] null to use Posted data
732	 * @return boolean
733	 */
734	public function validate($data = null)
735	{
736		return parent::validate($data);
737	}
738
739	/**
740	 * Set $set_backup option
741	 *
742	 * @param boolean $optval
743	 * @return e_pref
744	 *
745	 */
746	public function setOptionBackup($optval)
747	{
748		$this->set_backup = $optval;
749		return $this;
750	}
751
752	/**
753	 * Set $serial_bc option
754	 *
755	 * @param boolean $optval
756	 * @return e_pref
757	 *
758	 */
759	public function setOptionSerialize($optval)
760	{
761		$this->serial_bc = $optval;
762		return $this;
763	}
764
765    /**
766     * Override
767     */
768    public function delete($ids, $destroy = true, $session_messages = false)
769    {
770    }
771
772    /**
773     * Override
774     */
775    protected function dbUpdate($force = false, $session_messages = false)
776    {
777    }
778}
779
780/**
781 * Handle core preferences
782 *
783 * @package e107
784 * @category e107_handlers
785 * @version 1.0
786 * @author SecretR
787 * @copyright Copyright (c) 2009, e107 Inc.
788 */
789final class e_core_pref extends e_pref
790{
791	/**
792	 * Allowed core id array
793	 *
794	 * @var array
795	 */
796	public $aliases = array(
797		'core' 			=> 'SitePrefs',
798		'core_backup' 	=> 'SitePrefs_Backup',
799		'core_old' 		=> 'pref',
800		'emote' 		=> 'emote_default', //TODO include other emote packs of the user.
801		'menu' 			=> 'menu_pref',
802		'search' 		=> 'search_prefs',
803		'notify' 		=> 'notify_prefs',
804		'history'		=> 'history_prefs',
805	);
806
807	/**
808	 * Backward compatibility - list of prefid's which operate wit serialized data
809	 *
810	 * @var array
811	 */
812	// protected $serial_bc_array = array('core_old', 'emote', 'menu', 'search');
813	protected $serial_bc_array = array('core_old');
814
815	/**
816	 * Constructor
817	 *
818	 * @param string $alias
819	 * @param boolean $load load DB data on startup
820	 */
821	function __construct($alias, $load = true)
822	{
823
824
825		$pref_alias = $alias;
826
827		if($alias == 'emote')
828		{
829			$pack = e107::pref('core','emotepack');
830			$this->aliases['emote'] = 'emote_'.$pack;
831		}
832
833		$pref_id = $this->getConfigId($alias);
834
835
836		if(!$pref_id)
837		{
838			$pref_id = $pref_alias = '';
839			trigger_error('Core config ID '.$alias.' not found!', E_USER_WARNING);
840			return;
841		}
842
843		if(in_array($pref_alias, $this->serial_bc_array))
844		{
845			$this->setOptionSerialize(true);
846		}
847
848		if('core' === $pref_alias)
849		{
850			$this->setOptionBackup(true);
851		}
852
853		parent::__construct($pref_id, $pref_alias);
854		if($load && $pref_id)
855		{
856			$this->load();
857		}
858
859
860	}
861
862	/**
863	 * Get config ID
864	 * Allowed values: key or value from $alias array
865	 * If id not found this method returns false
866	 *
867	 * @param string $alias
868	 * @return string
869	 */
870	public function getConfigId($alias)
871	{
872		$alias = trim($alias);
873		if(isset($this->aliases[$alias]))
874		{
875			return $this->aliases[$alias];
876		}
877		return false;
878	}
879
880	/**
881	 * Get config ID
882	 * Allowed values: key or value from $alias array
883	 * If id not found this method returns false
884	 *
885	 * @param string $prefid
886	 * @return string
887	 */
888	public function getAlias($prefid)
889	{
890		$prefid = trim($prefid);
891		return array_search($prefid, $this->aliases);
892	}
893
894
895	/**
896	 * Export data from core pref and remove if needed. Useful for core pref -> menu table parm migration.
897	 * @param array $prefList  key/value pairs.  key = oldpref value = new pref key
898	 * @param bool|false $remove
899	 * @return array|false if no match found.
900	 */
901	public function migrateData($prefList=array(), $remove=false)
902	{
903		$data = self::getData();
904		$array = array();
905		$save = false;
906
907		if(empty($prefList))
908		{
909			return false;
910		}
911
912		foreach($data as $k=>$v)
913		{
914			if(isset($prefList[$k]))
915			{
916				$key = $prefList[$k];
917				$array[$key] = $v;
918
919				if($remove == true)
920				{
921					self::remove($k);
922					$save = true;
923				}
924			}
925
926		}
927
928		if(empty($array))
929		{
930			return false;
931		}
932
933		if(!empty($save))
934		{
935			self::save(false,true,false);
936		}
937
938		return $array;
939
940	}
941}
942
943/**
944 * Handle plugin preferences
945 *
946 * @package e107
947 * @category e107_handlers
948 * @version 1.0
949 * @author SecretR
950 * @copyright Copyright (c) 2009, e107 Inc.
951 */
952class e_plugin_pref extends e_pref
953{
954	/**
955	 * Unique plugin name
956	 *
957	 * @var string
958	 */
959	protected $plugin_id;
960
961	/**
962	 * Constructor
963	 * Note: object data will be loaded only if the plugin is installed (no matter of the passed
964	 * $load value)
965	 *
966	 * @param string $plugin_id unique plugin name
967	 * @param string $multi_row additional field identifier appended to the $prefid
968	 * @param boolean $load load on startup
969	 */
970	function __construct($plugin_id, $multi_row = '', $load = true)
971	{
972		$this->plugin_id = $plugin_id;
973		if($multi_row)
974		{
975			$plugin_id = $plugin_id.'_'.$multi_row;
976		}
977		parent::__construct('plugin_'.$plugin_id, "plugin_".$this->plugin_id);
978		if($load && e107::findPref('plug_installed/'.$this->plugin_id))
979		{
980			$this->load();
981		}
982	}
983
984	/**
985	 * Retrive unique plugin name
986	 *
987	 * @return string
988	 */
989	public function getPluginId()
990	{
991		return $this->plugin_id;
992	}
993
994	/**
995	 * Delete plugin preferences
996	 * @see e107_handlers/e_pref#delete()
997	 * @return boolean
998	 */
999	public function delete($ids, $destroy = true, $session_messages = false)
1000	{
1001		$ret = false;
1002		if($this->plugin_id)
1003		{
1004			$ret = e107::getDb($this->plugin_id)->delete('core', "e107_name='{$this->plugin_id}'");
1005			$this->destroy();
1006		}
1007		return $ret;
1008	}
1009}
1010
1011
1012/**
1013 * Handle plugin preferences
1014 *
1015 * @package e107
1016 * @category e107_handlers
1017 * @version 1.0
1018 * @author SecretR
1019 * @copyright Copyright (c) 2009, e107 Inc.
1020 */
1021class e_theme_pref extends e_pref
1022{
1023	/**
1024	 * Unique plugin name
1025	 *
1026	 * @var string
1027	 */
1028	protected $theme_id;
1029
1030	/**
1031	 * Constructor
1032	 * Note: object data will be loaded only if the plugin is installed (no matter of the passed
1033	 * $load value)
1034	 *
1035	 * @param string $theme_id unique plugin name
1036	 * @param string $multi_row additional field identifier appended to the $prefid
1037	 * @param boolean $load load on startup
1038	 */
1039	function __construct($theme_id, $multi_row = '', $load = true)
1040	{
1041		$this->theme_id = $theme_id;
1042		if($multi_row)
1043		{
1044			$theme_id = $theme_id.'_'.$multi_row;
1045		}
1046		parent::__construct('theme_'.$theme_id, "theme_".$this->theme_id);
1047	//	if($load && e107::findPref('plug_installed/'.$this->theme_id))
1048		{
1049			$this->load();
1050		}
1051	}
1052
1053	/**
1054	 * Retrive unique plugin name
1055	 *
1056	 * @return string
1057	 */
1058	public function getPluginId()
1059	{
1060		return $this->theme_id;
1061	}
1062
1063	/**
1064	 * Delete plugin preferences
1065	 * @see e107_handlers/e_pref#delete()
1066	 * @return boolean
1067	 */
1068	public function delete($ids, $destroy = true, $session_messages = false)
1069	{
1070		$ret = false;
1071		if($this->theme_id)
1072		{
1073			$ret = e107::getDb($this->theme_id)->delete('core', "e107_name='{$this->theme_id}'");
1074			$this->destroy();
1075		}
1076		return $ret;
1077	}
1078}
1079
1080
1081
1082
1083
1084
1085
1086/**
1087 * DEPRECATED - see e107::getConfig(), e_core_pref and e_plugin_pref
1088 *
1089 */
1090//
1091// Simple functionality:
1092// Grab all prefs once, in one DB query. Reuse them throughout the session.
1093//
1094// get/set methods serve/consume strings (with slashes taken care of)
1095// getArray/setArray methods serve/consume entire arrays (since most prefs are such!)
1096//
1097// NOTE: Use of this class is VALUABLE (efficient) yet not NECESSARY (i.e. the system
1098//       will not break if it is ignored)... AS LONG AS there is no path consisting of:
1099//             - modify pref value(s) IGNORING this class
1100//  - retrieve pref value(s) USING this class
1101//       (while processing a single web page)
1102//  Just to be safe I have changed a number of menu_pref edits to use setArray().
1103//
1104
1105class prefs
1106{
1107	var $prefVals;
1108	var $prefArrays;
1109
1110	// Default prefs to load
1111	var $DefaultRows = "e107_name='e107' OR e107_name='menu_pref' OR e107_name='notify_prefs'";
1112
1113	// Read prefs from DB - get as many rows as are required with a single query.
1114	// $RowList is an array of pref entries to retrieve.
1115	// If $use_default is TRUE, $RowList entries are added to the default array. Otherwise only $RowList is used.
1116	// Returns TRUE on success (measured as getting at least one row of data); false on error.
1117	// Any data read is buffered (in serialised form) here - retrieve using get()
1118	function ExtractPrefs($RowList = "", $use_default = FALSE)
1119	{
1120		global $sql;
1121		$Args = '';
1122		if($use_default)
1123		{
1124			$Args = $this->DefaultRows;
1125		}
1126		if(is_array($RowList))
1127		{
1128			foreach($RowList as $v)
1129			{
1130				$Args .= ($Args ? " OR e107_name='{$v}'" : "e107_name='{$v}'");
1131			}
1132		}
1133		if (!$sql->select('core', '*', $Args, 'default'))
1134		{
1135			return FALSE;
1136		}
1137		while ($row = $sql->fetch())
1138		{
1139			$this->prefVals['core'][$row['e107_name']] = $row['e107_value'];
1140		}
1141		return TRUE;
1142	}
1143
1144
1145	/**
1146	* Return current pref string $name from $table (only core for now)
1147	*
1148	* @param  string $name -- name of pref row
1149	* @param  string $table -- "core"
1150	* @return  string pref value, slashes already stripped. FALSE on error
1151	* @access  public
1152	*/
1153	function get($Name)
1154	{
1155		if(isset($this->prefVals['core'][$Name]))
1156		{
1157			if($this->prefVals['core'][$Name] != '### ROW CACHE FALSE ###')
1158			{
1159				return $this->prefVals['core'][$Name];		// Dava from cache
1160			}
1161			else
1162			{
1163				return false;
1164			}
1165		}
1166
1167		// Data not in cache - retrieve from DB
1168		$get_sql = new db; // required so sql loops don't break using $tp->toHTML().
1169		if($get_sql->db_Select('core', '*', "`e107_name` = '{$Name}'", 'default'))
1170		{
1171			$row = $get_sql->db_Fetch();
1172			$this->prefVals['core'][$Name] = $row['e107_value'];
1173			return $this->prefVals['core'][$Name];
1174		}
1175		else
1176		{	// Data not in DB - put a 'doesn't exist' entry in cache to save another DB access
1177			$this->prefVals['core'][$Name] = '### ROW CACHE FALSE ###';
1178			return false;
1179		}
1180	}
1181
1182	/**
1183	* Return current array from pref string $name in $table (core only for now)
1184	*
1185	* @param  string $name -- name of pref row
1186	* @param  string $table -- "core" only now
1187	* @return  array pref values
1188	* @access     public
1189	*/
1190	// retrieve prefs as an array of values
1191	function getArray($name)
1192	{
1193		return e107::unserialize($this->get($name));
1194		// return unserialize($this->get($name));
1195	}
1196
1197
1198	/**
1199	* Update pref set and cache
1200	*
1201	* @param  string val -- pre-serialized string
1202	* @param  string $name -- name of pref row
1203	* @param  string $table -- "core" or "user"
1204	* @global  mixed $$name
1205	* @access  public
1206	*
1207	* set("val")    == 'core', 'pref'
1208	* set("val","rowname")   == 'core', rowname
1209	* set("val","","user")   == 'user', 'user_pref' for current user
1210	* set("val","","user",uid)   == 'user', 'user_pref' for user uid
1211	* set("val","fieldname","user")  == 'user', fieldname
1212	*
1213	*/
1214	function set($val, $name = "", $table = "core", $uid = USERID) {
1215		global $sql;
1216		if (!strlen($name)) {
1217			switch ($table) {
1218				case 'core':
1219				$name = "pref";
1220				break;
1221				case 'user':
1222				$name = "user_pref";
1223				break;
1224			}
1225		}
1226		$val = addslashes($val);
1227
1228		switch ($table ) {
1229			case 'core':
1230			if(!$sql->db_Update($table, "e107_value='$val' WHERE e107_name='$name'"))
1231			{
1232				$sql->db_Insert($table, "'{$name}', '{$val}'");
1233			}
1234			$this->prefVals[$table][$name] = $val;
1235			unset($this->prefArrays[$table][$name]);
1236			break;
1237			case 'user':
1238			$sql->db_Update($table, "user_prefs='$val' WHERE user_id=$uid");
1239			break;
1240		}
1241	}
1242
1243
1244	/**
1245	* Update pref set and cache
1246	*
1247	* - @param  string $name -- name of pref row
1248	* - @param  string $table -- "core" or "user"
1249	* - @global  $$name
1250	* - @access  public
1251	*
1252	* set()    == core, pref
1253	* set("rowname")   == core, rowname
1254	* set("","user")   == user, user_pref for current user
1255	* set("","user",uid)   == user, user_pref for user uid
1256	* set("fieldname","user")  == user, fieldname
1257	*
1258	* all pref sets other than menu_pref get toDB()
1259	*/
1260	function setArray($name = '', $table = 'core', $uid = USERID)
1261	{
1262		$tp = e107::getParser();
1263
1264		if (!strlen($name))
1265		{
1266			switch ($table)
1267			{
1268				case 'core':
1269				$name = 'pref';
1270				break;
1271				case 'user':
1272				$name = 'user_pref';
1273				break;
1274			}
1275		}
1276
1277		global $$name;
1278		if ($name != 'menu_pref')
1279		{
1280			foreach($$name as $key => $prefvalue)
1281			{
1282				$$name[$key] = $tp->toDB($prefvalue);
1283			}
1284		}
1285		$tmp = e107::getArrayStorage()->WriteArray($$name, FALSE);		// $this->set() adds slashes now
1286	//	$tmp = serialize($$name);
1287		$this->set($tmp, $name, $table, $uid);
1288	}
1289}
1290
1291