|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* @link http://www.tintsoft.com/ |
|
4
|
|
|
* @copyright Copyright (c) 2012 TintSoft Technology Co. Ltd. |
|
5
|
|
|
* @license http://www.tintsoft.com/license/ |
|
6
|
|
|
*/ |
|
7
|
|
|
|
|
8
|
|
|
namespace yuncms\components; |
|
9
|
|
|
|
|
10
|
|
|
use Yii; |
|
11
|
|
|
use yii\base\Component; |
|
12
|
|
|
use yii\caching\Cache; |
|
13
|
|
|
|
|
14
|
|
|
/** |
|
15
|
|
|
* @author Aris Karageorgos <[email protected]> |
|
16
|
|
|
*/ |
|
17
|
|
|
class Settings extends Component |
|
18
|
|
|
{ |
|
19
|
|
|
/** |
|
20
|
|
|
* @var string settings model. Make sure your settings model calls clearCache in the afterSave callback |
|
21
|
|
|
*/ |
|
22
|
|
|
public $modelClass = 'yuncms\models\BaseSetting'; |
|
23
|
|
|
|
|
24
|
|
|
/** |
|
25
|
|
|
* Model to for storing and retrieving settings |
|
26
|
|
|
* @var \yuncms\models\SettingInterface |
|
27
|
|
|
*/ |
|
28
|
|
|
protected $model; |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* @var Cache|string the cache object or the application component ID of the cache object. |
|
32
|
|
|
* Settings will be cached through this cache object, if it is available. |
|
33
|
|
|
* |
|
34
|
|
|
* After the Settings object is created, if you want to change this property, |
|
35
|
|
|
* you should only assign it with a cache object. |
|
36
|
|
|
* Set this property to null if you do not want to cache the settings. |
|
37
|
|
|
*/ |
|
38
|
|
|
public $cache = 'cache'; |
|
39
|
|
|
|
|
40
|
|
|
/** |
|
41
|
|
|
* @var Cache|string the front cache object or the application component ID of the front cache object. |
|
42
|
|
|
* Front cache will be cleared through this cache object, if it is available. |
|
43
|
|
|
* |
|
44
|
|
|
* After the Settings object is created, if you want to change this property, |
|
45
|
|
|
* you should only assign it with a cache object. |
|
46
|
|
|
* Set this property to null if you do not want to clear the front cache. |
|
47
|
|
|
*/ |
|
48
|
|
|
public $frontCache; |
|
49
|
|
|
|
|
50
|
|
|
/** |
|
51
|
|
|
* To be used by the cache component. |
|
52
|
|
|
* |
|
53
|
|
|
* @var string cache key |
|
54
|
|
|
*/ |
|
55
|
|
|
public $cacheKey = 'yuncms.settings'; |
|
56
|
|
|
|
|
57
|
|
|
/** |
|
58
|
|
|
* Holds a cached copy of the data for the current request |
|
59
|
|
|
* |
|
60
|
|
|
* @var mixed |
|
61
|
|
|
*/ |
|
62
|
|
|
private $_data = null; |
|
63
|
|
|
|
|
64
|
|
|
/** |
|
65
|
|
|
* Initialize the component |
|
66
|
|
|
*/ |
|
67
|
|
|
public function init() |
|
68
|
|
|
{ |
|
69
|
|
|
parent::init(); |
|
70
|
|
|
|
|
71
|
|
|
$this->model = new $this->modelClass; |
|
72
|
|
|
|
|
73
|
|
|
if (is_string($this->cache)) { |
|
74
|
|
|
$this->cache = Yii::$app->get($this->cache, false); |
|
|
|
|
|
|
75
|
|
|
} |
|
76
|
|
|
if (is_string($this->frontCache)) { |
|
77
|
|
|
$this->frontCache = Yii::$app->get($this->frontCache, false); |
|
|
|
|
|
|
78
|
|
|
} |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* Get's the value for the given key and section. |
|
83
|
|
|
* You can use dot notation to separate the section from the key: |
|
84
|
|
|
* $value = $settings->get('section.key'); |
|
85
|
|
|
* and |
|
86
|
|
|
* $value = $settings->get('key', 'section'); |
|
87
|
|
|
* are equivalent |
|
88
|
|
|
* |
|
89
|
|
|
* @param $key |
|
90
|
|
|
* @param string|null $section |
|
91
|
|
|
* @param string|null $default |
|
92
|
|
|
* @return mixed |
|
93
|
|
|
*/ |
|
94
|
|
|
public function get($key, $section = null, $default = null) |
|
95
|
|
|
{ |
|
96
|
|
|
if (is_null($section)) { |
|
97
|
|
|
$pieces = explode('.', $key, 2); |
|
98
|
|
|
if (count($pieces) > 1) { |
|
99
|
|
|
$section = $pieces[0]; |
|
100
|
|
|
$key = $pieces[1]; |
|
101
|
|
|
} else { |
|
102
|
|
|
$section = ''; |
|
103
|
|
|
} |
|
104
|
|
|
} |
|
105
|
|
|
|
|
106
|
|
|
$data = $this->getRawConfig(); |
|
107
|
|
|
|
|
108
|
|
|
if (isset($data[$section][$key][0])) { |
|
109
|
|
|
if (in_array($data[$section][$key][1], ['object', 'boolean', 'bool', 'integer', 'int', 'float', 'string', 'array'])) { |
|
110
|
|
|
settype($data[$section][$key][0], $data[$section][$key][1]); |
|
111
|
|
|
} |
|
112
|
|
|
} else { |
|
113
|
|
|
$data[$section][$key][0] = $default; |
|
114
|
|
|
} |
|
115
|
|
|
return $data[$section][$key][0]; |
|
116
|
|
|
} |
|
117
|
|
|
|
|
118
|
|
|
/** |
|
119
|
|
|
* Checks to see if a setting exists. |
|
120
|
|
|
* If $searchDisabled is set to true, calling this function will result in an additional query. |
|
121
|
|
|
* @param $key |
|
122
|
|
|
* @param string|null $section |
|
123
|
|
|
* @param boolean $searchDisabled |
|
124
|
|
|
* @return boolean |
|
125
|
|
|
*/ |
|
126
|
|
|
public function has($key, $section = null, $searchDisabled = false) |
|
127
|
|
|
{ |
|
128
|
|
|
if ($searchDisabled) { |
|
129
|
|
|
$setting = $this->model->findSetting($key, $section); |
|
130
|
|
|
} else { |
|
131
|
|
|
$setting = $this->get($key, $section); |
|
132
|
|
|
} |
|
133
|
|
|
return is_null($setting) ? false : true; |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
|
|
/** |
|
137
|
|
|
* 设置 |
|
138
|
|
|
* @param string $key |
|
139
|
|
|
* @param mixed $value |
|
140
|
|
|
* @param null|string $section |
|
141
|
|
|
* @param null|string $type |
|
142
|
|
|
* @return boolean |
|
143
|
|
|
* @throws \yii\base\InvalidConfigException |
|
144
|
|
|
*/ |
|
145
|
|
|
public function set($key, $value, $section = null, $type = null) |
|
146
|
|
|
{ |
|
147
|
|
|
if (is_null($section)) { |
|
148
|
|
|
$pieces = explode('.', $key); |
|
149
|
|
|
$section = $pieces[0]; |
|
150
|
|
|
$key = $pieces[1]; |
|
151
|
|
|
} |
|
152
|
|
|
|
|
153
|
|
|
if ($this->model->setSetting($section, $key, $value, $type)) { |
|
154
|
|
|
return true; |
|
155
|
|
|
} |
|
156
|
|
|
return false; |
|
157
|
|
|
} |
|
158
|
|
|
|
|
159
|
|
|
/** |
|
160
|
|
|
* Returns the specified key or sets the key with the supplied (default) value |
|
161
|
|
|
* |
|
162
|
|
|
* @param string $key |
|
163
|
|
|
* @param mixed $value |
|
164
|
|
|
* @param null|string $section |
|
165
|
|
|
* @param null|string $type |
|
166
|
|
|
* |
|
167
|
|
|
* @return bool|mixed |
|
168
|
|
|
* @throws \yii\base\InvalidConfigException |
|
169
|
|
|
*/ |
|
170
|
|
|
public function getOrSet($key, $value, $section = null, $type = null) |
|
171
|
|
|
{ |
|
172
|
|
|
if ($this->has($key, $section, true)) { |
|
173
|
|
|
return $this->get($key, $section); |
|
174
|
|
|
} else { |
|
175
|
|
|
return $this->set($key, $value, $section, $type); |
|
176
|
|
|
} |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
/** |
|
180
|
|
|
* Deletes a setting |
|
181
|
|
|
* |
|
182
|
|
|
* @param $key |
|
183
|
|
|
* @param null|string $section |
|
184
|
|
|
* @return bool |
|
185
|
|
|
*/ |
|
186
|
|
|
public function delete($key, $section = null) |
|
187
|
|
|
{ |
|
188
|
|
|
if (is_null($section)) { |
|
189
|
|
|
$pieces = explode('.', $key); |
|
190
|
|
|
$section = $pieces[0]; |
|
191
|
|
|
$key = $pieces[1]; |
|
192
|
|
|
} |
|
193
|
|
|
return $this->model->deleteSetting($section, $key); |
|
194
|
|
|
} |
|
195
|
|
|
|
|
196
|
|
|
/** |
|
197
|
|
|
* Deletes all setting. Be careful! |
|
198
|
|
|
* |
|
199
|
|
|
* @return bool |
|
200
|
|
|
*/ |
|
201
|
|
|
public function deleteAll() |
|
202
|
|
|
{ |
|
203
|
|
|
return $this->model->deleteAllSettings(); |
|
204
|
|
|
} |
|
205
|
|
|
|
|
206
|
|
|
/** |
|
207
|
|
|
* Activates a setting |
|
208
|
|
|
* |
|
209
|
|
|
* @param $key |
|
210
|
|
|
* @param null|string $section |
|
211
|
|
|
* @return bool |
|
212
|
|
|
*/ |
|
213
|
|
|
public function activate($key, $section = null) |
|
214
|
|
|
{ |
|
215
|
|
|
if (is_null($section)) { |
|
216
|
|
|
$pieces = explode('.', $key); |
|
217
|
|
|
$section = $pieces[0]; |
|
218
|
|
|
$key = $pieces[1]; |
|
219
|
|
|
} |
|
220
|
|
|
return $this->model->activateSetting($section, $key); |
|
221
|
|
|
} |
|
222
|
|
|
|
|
223
|
|
|
/** |
|
224
|
|
|
* Deactivates a setting |
|
225
|
|
|
* |
|
226
|
|
|
* @param $key |
|
227
|
|
|
* @param null|string $section |
|
228
|
|
|
* @return bool |
|
229
|
|
|
*/ |
|
230
|
|
|
public function deactivate($key, $section = null) |
|
231
|
|
|
{ |
|
232
|
|
|
if (is_null($section)) { |
|
233
|
|
|
$pieces = explode('.', $key); |
|
234
|
|
|
$section = $pieces[0]; |
|
235
|
|
|
$key = $pieces[1]; |
|
236
|
|
|
} |
|
237
|
|
|
return $this->model->deactivateSetting($section, $key); |
|
238
|
|
|
} |
|
239
|
|
|
|
|
240
|
|
|
/** |
|
241
|
|
|
* Clears the settings cache on demand. |
|
242
|
|
|
* If you haven't configured cache this does nothing. |
|
243
|
|
|
* |
|
244
|
|
|
* @return boolean True if the cache key was deleted and false otherwise |
|
245
|
|
|
*/ |
|
246
|
|
|
public function clearCache() |
|
247
|
|
|
{ |
|
248
|
|
|
$this->_data = null; |
|
249
|
|
|
if ($this->frontCache instanceof Cache) { |
|
250
|
|
|
$this->frontCache->delete($this->cacheKey); |
|
251
|
|
|
} |
|
252
|
|
|
if ($this->cache instanceof Cache) { |
|
253
|
|
|
return $this->cache->delete($this->cacheKey); |
|
254
|
|
|
} |
|
255
|
|
|
return true; |
|
256
|
|
|
} |
|
257
|
|
|
|
|
258
|
|
|
/** |
|
259
|
|
|
* Returns the raw configuration array |
|
260
|
|
|
* |
|
261
|
|
|
* @return array |
|
262
|
|
|
*/ |
|
263
|
|
|
public function getRawConfig() |
|
264
|
|
|
{ |
|
265
|
|
|
if ($this->_data === null) { |
|
266
|
|
|
if ($this->cache instanceof Cache) { |
|
267
|
|
|
|
|
268
|
|
|
$data = $this->cache->get($this->cacheKey); |
|
269
|
|
|
|
|
270
|
|
|
if ($data === false) { |
|
271
|
|
|
$data = $this->model->getSettings(); |
|
272
|
|
|
$this->cache->set($this->cacheKey, $data); |
|
273
|
|
|
} |
|
274
|
|
|
} else { |
|
275
|
|
|
$data = $this->model->getSettings(); |
|
276
|
|
|
} |
|
277
|
|
|
$this->_data = $data; |
|
278
|
|
|
} |
|
279
|
|
|
return $this->_data; |
|
280
|
|
|
} |
|
281
|
|
|
} |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountIdthat can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theidproperty of an instance of theAccountclass. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.