Commit | Line | Data |
---|---|---|
3a84c0ab TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
4 | | CiviCRM version 4.7 | | |
5 | +--------------------------------------------------------------------+ | |
6 | | Copyright CiviCRM LLC (c) 2004-2015 | | |
7 | +--------------------------------------------------------------------+ | |
8 | | This file is a part of CiviCRM. | | |
9 | | | | |
10 | | CiviCRM is free software; you can copy, modify, and distribute it | | |
11 | | under the terms of the GNU Affero General Public License | | |
12 | | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | | |
13 | | | | |
14 | | CiviCRM is distributed in the hope that it will be useful, but | | |
15 | | WITHOUT ANY WARRANTY; without even the implied warranty of | | |
16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | | |
17 | | See the GNU Affero General Public License for more details. | | |
18 | | | | |
19 | | You should have received a copy of the GNU Affero General Public | | |
20 | | License and the CiviCRM Licensing Exception along | | |
21 | | with this program; if not, contact CiviCRM LLC | | |
22 | | at info[AT]civicrm[DOT]org. If you have questions about the | | |
23 | | GNU Affero General Public License or the licensing of CiviCRM, | | |
24 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | | |
25 | +--------------------------------------------------------------------+ | |
26 | */ | |
27 | ||
28 | namespace Civi\Core; | |
29 | ||
30 | /** | |
31 | * Class SettingsBag | |
32 | * @package Civi\Core | |
33 | * | |
34 | * Read and write settings for a given domain (or contact). | |
35 | * | |
36 | * If the target entity does not already have a value for the setting, then | |
37 | * the defaults will be used. If mandatory values are provided, they will | |
38 | * override any defaults or custom settings. | |
39 | * | |
40 | * It's expected that the SettingsBag will have O(50-250) settings -- and that | |
41 | * we'll load the full bag on many page requests. Consequently, we don't | |
42 | * want the full metadata (help text and version history and HTML widgets) | |
43 | * for all 250 settings, but we do need the default values. | |
44 | * | |
45 | * This class is not usually instantiated directly. Instead, use SettingsManager | |
46 | * or Civi::settings(). | |
47 | * | |
48 | * @see \Civi::settings() | |
49 | * @see SettingsManagerTest | |
50 | */ | |
51 | class SettingsBag { | |
52 | ||
53 | protected $domainId; | |
54 | ||
55 | protected $contactId; | |
56 | ||
57 | /** | |
58 | * @var array | |
59 | * Array(string $settingName => mixed $value). | |
60 | */ | |
61 | protected $defaults; | |
62 | ||
63 | /** | |
64 | * @var array | |
65 | * Array(string $settingName => mixed $value). | |
66 | */ | |
67 | protected $mandatory; | |
68 | ||
69 | /** | |
70 | * The result of combining default values, mandatory | |
71 | * values, and user values. | |
72 | * | |
73 | * @var array|NULL | |
74 | * Array(string $settingName => mixed $value). | |
75 | */ | |
76 | protected $combined; | |
77 | ||
78 | /** | |
79 | * @var array | |
80 | */ | |
81 | protected $values; | |
82 | ||
9fd040ae TO |
83 | protected $filteredValues; |
84 | ||
3a84c0ab TO |
85 | /** |
86 | * @param int $domainId | |
87 | * The domain for which we want settings. | |
88 | * @param int|NULL $contactId | |
89 | * The contact for which we want settings. Use NULL for domain settings. | |
90 | * @param array $defaults | |
91 | * Array(string $settingName => mixed $value). | |
92 | * @param array $mandatory | |
93 | * Array(string $settingName => mixed $value). | |
94 | */ | |
95 | public function __construct($domainId, $contactId, $defaults, $mandatory) { | |
96 | $this->domainId = $domainId; | |
97 | $this->contactId = $contactId; | |
98 | $this->defaults = $defaults; | |
99 | $this->mandatory = $mandatory; | |
100 | $this->combined = NULL; | |
101 | } | |
102 | ||
103 | /** | |
104 | * Load all settings that apply to this domain or contact. | |
105 | * | |
106 | * @return $this | |
107 | */ | |
108 | public function load() { | |
109 | $this->values = array(); | |
110 | $dao = $this->createDao(); | |
111 | $dao->find(); | |
112 | while ($dao->fetch()) { | |
9fd040ae | 113 | $this->values[$dao->name] = ($dao->value !== NULL) ? unserialize($dao->value) : NULL; |
3a84c0ab TO |
114 | } |
115 | $this->combined = NULL; | |
116 | return $this; | |
117 | } | |
118 | ||
119 | /** | |
120 | * Add a batch of settings. Save them. | |
121 | * | |
122 | * @param array $settings | |
123 | * Array(string $settingName => mixed $settingValue). | |
124 | * @return $this | |
125 | */ | |
126 | public function add(array $settings) { | |
127 | foreach ($settings as $key => $value) { | |
128 | $this->set($key, $value); | |
129 | } | |
130 | return $this; | |
131 | } | |
132 | ||
133 | /** | |
134 | * Get a list of all effective settings. | |
135 | * | |
136 | * @return array | |
137 | * Array(string $settingName => mixed $settingValue). | |
138 | */ | |
139 | public function all() { | |
140 | if ($this->combined === NULL) { | |
141 | $this->combined = $this->combine( | |
142 | array($this->defaults, $this->values, $this->mandatory) | |
143 | ); | |
144 | } | |
145 | return $this->combined; | |
146 | } | |
147 | ||
148 | /** | |
149 | * Determine the effective value. | |
150 | * | |
151 | * @param string $key | |
152 | * @return mixed | |
153 | */ | |
154 | public function get($key) { | |
155 | $all = $this->all(); | |
156 | return isset($all[$key]) ? $all[$key] : NULL; | |
157 | } | |
158 | ||
9fd040ae TO |
159 | /** |
160 | * Get the value of a setting, formatted as a path. | |
161 | * | |
162 | * @param string $key | |
163 | * @return string|NULL | |
164 | * Absolute path. | |
165 | */ | |
166 | public function getPath($key) { | |
167 | if (!isset($this->filteredValues[$key])) { | |
7a77331e | 168 | $this->filteredValues[$key] = $this->filterPath($this->get($key)); |
9fd040ae TO |
169 | } |
170 | return $this->filteredValues[$key]; | |
171 | } | |
172 | ||
173 | /** | |
174 | * Get the value of a setting, formatted as a URL. | |
175 | * | |
176 | * @param string $key | |
177 | * @param bool $preferFormat | |
178 | * The preferred format ('absolute', 'relative'). | |
179 | * The result data may not meet the preference -- if the setting | |
180 | * refers to an external domain, then the result will be | |
181 | * absolute (regardless of preference). | |
182 | * @parma bool|NULL $ssl | |
183 | * NULL to autodetect. TRUE to force to SSL. | |
184 | * @return string|NULL | |
185 | * URL. | |
186 | */ | |
187 | public function getUrl($key, $preferFormat, $ssl = NULL) { | |
188 | if (!isset($this->filteredValues[$key][$preferFormat][$ssl])) { | |
189 | $value = $this->filterUrl($this->get($key), $preferFormat, $ssl); | |
190 | $this->filteredValues[$key][$preferFormat][$ssl] = $value; | |
191 | } | |
192 | return $this->filteredValues[$key][$preferFormat][$ssl]; | |
193 | } | |
194 | ||
3a84c0ab TO |
195 | /** |
196 | * Determine the explicitly designated value, regardless of | |
197 | * any default or mandatory values. | |
198 | * | |
199 | * @param string $key | |
200 | * @return null | |
201 | */ | |
202 | public function getExplicit($key) { | |
203 | return (isset($this->values[$key]) ? $this->values[$key] : NULL); | |
204 | } | |
205 | ||
206 | /** | |
207 | * Determine if the entity has explicitly designated a value. | |
208 | * | |
209 | * Note that get() may still return other values based on | |
210 | * mandatory values or defaults. | |
211 | * | |
212 | * @param string $key | |
213 | * @return bool | |
214 | */ | |
215 | public function hasExplict($key) { | |
216 | // NULL means no designated value. | |
217 | return isset($this->values[$key]); | |
218 | } | |
219 | ||
220 | /** | |
221 | * Removes any explicit settings. This restores the default. | |
222 | * | |
223 | * @param string $key | |
224 | * @return $this | |
225 | */ | |
226 | public function revert($key) { | |
227 | // It might be better to DELETE (to avoid long-term leaks), | |
228 | // but setting NULL is simpler for now. | |
229 | return $this->set($key, NULL); | |
230 | } | |
231 | ||
232 | /** | |
233 | * Add a single setting. Save it. | |
234 | * | |
235 | * @param string $key | |
236 | * @param mixed $value | |
237 | * @return $this | |
238 | */ | |
239 | public function set($key, $value) { | |
240 | $this->setDb($key, $value); | |
241 | $this->values[$key] = $value; | |
9fd040ae | 242 | unset($this->filteredValues[$key]); |
3a84c0ab TO |
243 | $this->combined = NULL; |
244 | return $this; | |
245 | } | |
246 | ||
9fd040ae TO |
247 | /** |
248 | * @param string $key | |
249 | * @param string $value | |
250 | * Absolute path. | |
251 | * @return $this | |
252 | */ | |
253 | public function setPath($key, $value) { | |
254 | $this->set($key, \CRM_Utils_File::relativeDirectory($value)); | |
255 | return $this; | |
256 | } | |
257 | ||
258 | /** | |
259 | * @param string $key | |
260 | * @param string $value | |
261 | * Absolute URL. | |
262 | * @return $this | |
263 | */ | |
264 | public function setUrl($key, $value) { | |
265 | $this->set($key, \CRM_Utils_System::relativeURL($value)); | |
266 | return $this; | |
267 | } | |
268 | ||
3a84c0ab TO |
269 | /** |
270 | * @return \CRM_Core_DAO_Setting | |
271 | */ | |
272 | protected function createDao() { | |
273 | $dao = new \CRM_Core_DAO_Setting(); | |
274 | $dao->domain_id = $this->domainId; | |
275 | if ($this->contactId === NULL) { | |
276 | $dao->is_domain = 1; | |
277 | } | |
278 | else { | |
279 | $dao->contact_id = $this->contactId; | |
280 | $dao->is_domain = 0; | |
281 | } | |
282 | return $dao; | |
283 | } | |
284 | ||
285 | /** | |
286 | * Combine a series of arrays, excluding any | |
287 | * null values. Later values override earlier | |
288 | * values. | |
289 | * | |
290 | * @param $arrays | |
291 | * @return array | |
292 | */ | |
293 | protected function combine($arrays) { | |
294 | $combined = array(); | |
295 | foreach ($arrays as $array) { | |
296 | foreach ($array as $k => $v) { | |
297 | if ($v !== NULL) { | |
298 | $combined[$k] = $v; | |
299 | } | |
300 | } | |
301 | } | |
302 | return $combined; | |
303 | } | |
304 | ||
305 | /** | |
306 | * @param $key | |
307 | * @param $value | |
308 | */ | |
309 | protected function setDb($name, $value) { | |
310 | $fields = array(); | |
311 | $fieldsToSet = \CRM_Core_BAO_Setting::validateSettingsInput(array($name => $value), $fields); | |
312 | //We haven't traditionally validated inputs to setItem, so this breaks things. | |
313 | //foreach ($fieldsToSet as $settingField => &$settingValue) { | |
314 | // self::validateSetting($settingValue, $fields['values'][$settingField]); | |
315 | //} | |
316 | // NOTE: We don't have any notion of createdID | |
317 | \CRM_Core_BAO_Setting::_setItem($fields['values'][$name], $value, '', $name, NULL, $this->contactId, NULL, $this->domainId); | |
318 | ||
319 | //$dao = $this->createDao(); | |
320 | //$dao->name = $key; | |
321 | //$dao->group_name = ''; | |
322 | //$dao->find(); | |
323 | //$serializedValue = ($value === NULL ? 'null' : serialize($value)); | |
324 | //if ($dao->value !== $serializedValue) { | |
325 | // $dao->created_date = \CRM_Utils_Time::getTime('Ymdhis'); | |
326 | // $dao->value = $serializedValue; | |
327 | // $dao->save(); | |
328 | //} | |
329 | } | |
330 | ||
9fd040ae TO |
331 | /** |
332 | * Filter a URL, the same way that it would be if it were read from settings. | |
333 | * | |
334 | * @param $value | |
335 | * @param $preferFormat | |
336 | * @param $ssl | |
337 | * @return mixed|string | |
338 | */ | |
339 | public function filterUrl($value, $preferFormat, $ssl = NULL) { | |
340 | if ($value) { | |
341 | $value = \CRM_Utils_System::absoluteURL($value, TRUE); | |
342 | } | |
343 | if ($preferFormat === 'relative' && $value) { | |
344 | $parsed = parse_url($value); | |
345 | if (isset($_SERVER['HTTP_HOST']) && isset($parsed['host']) && $_SERVER['HTTP_HOST'] == $parsed['host']) { | |
346 | $value = $parsed['path']; | |
347 | } | |
348 | } | |
349 | ||
350 | if ($value) { | |
351 | if ($ssl || ($ssl === NULL && \CRM_Utils_System::isSSL())) { | |
352 | $value = str_replace('http://', 'https://', $value); | |
9fd040ae | 353 | } |
9fd040ae TO |
354 | } |
355 | return $value; | |
356 | } | |
357 | ||
7a77331e TO |
358 | /** |
359 | * @param string $value | |
360 | * @return bool|string | |
361 | */ | |
362 | public function filterPath($value) { | |
363 | if ($value) { | |
364 | return \CRM_Utils_File::absoluteDirectory($value); | |
365 | } | |
366 | else { | |
367 | return FALSE; | |
368 | } | |
369 | } | |
370 | ||
3a84c0ab | 371 | } |