Issues (41)

src/protected/models/Setting.php (7 issues)

1
<?php
2
3
/**
4
 * This is the model class for table "settings".
5
 *
6
 * The followings are the available columns in table 'settings':
7
 * @property string $name
8
 * @property string $value
9
 * 
10
 * @author Sam Stenvall <[email protected]>
11
 * @copyright Copyright &copy; Sam Stenvall 2014-
12
 * @license https://www.gnu.org/licenses/gpl.html The GNU General Public License v3.0
13
 */
14
class Setting extends CActiveRecord
15
{
16
17
	// Setting types
18
	const TYPE_TEXT = 'text';
19
	const TYPE_TEXT_WIDE = 'text-wide';
20
	const TYPE_CHECKBOX = 'checkbox';
21
	const TYPE_CHECKBOX_LIST = 'checkbox-list';
22
	const TYPE_DROPDOWN = 'dropdown';
23
24
	// Option type for checklists
25
	const POWER_OPTION_SHUTDOWN = 'shutdown';
26
	const POWER_OPTION_SUSPEND = 'suspend';
27
	const POWER_OPTION_HIBERNATE = 'hibernate';
28
	const POWER_OPTION_REBOOT = 'reboot';
29
30
	// We need one attribute per setting
31
	public $language;
32
	public $applicationName;
33
	public $applicationSubtitle;
34
	public $singleFilePlaylist;
35
	public $showHelpBlocks;
36
	public $cacheApiCalls;
37
	public $enableActorTypeahead;
38
	public $allowUserPowerOff;
39
	public $pagesize;
40
	public $useHttpsForVfsUrls;
41
	public $whitelist;
42
	public $ignoreArticle;
43
	public $playlistFormat;
44
	public $requestTimeout;
45
46
	/**
47
	 * @var Setting[] list of all settings and their current values (runtime 
48
	 * cache)
49
	 */
50
	private static $_settings;
51
	
52
	/**
53
	 * Returns the specified setting's value as a boolean
54
	 * @param string $setting the setting
55
	 * @return boolean the value
56
	 */
57
	public static function getBoolean($setting)
58
	{
59
		return (boolean)self::getValue($setting);
60
	}
61
62
	/**
63
	 * Returns whether the given option is set for the specified setting
64
	 * @param string $setting the setting
65
	 * @param string $option the option
66
	 * @return whether the option is set or not
0 ignored issues
show
The type whether was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
67
	 */
68
	public static function getBooleanOption($setting, $option)
69
	{
70
		$value = self::getValue($setting);
71
		return is_array($value) && in_array($option, $value);
0 ignored issues
show
Bug Best Practice introduced by
The expression return is_array($value) ..._array($option, $value) returns the type boolean which is incompatible with the documented return type whether.
Loading history...
72
	}
73
74
	/**
75
	 * Returns the specified setting's value as an integer
76
	 * @param string $setting the setting
77
	 * @return int the value
78
	 */
79
	public static function getInteger($setting)
80
	{
81
		return (int)self::getValue($setting);
82
	}
83
84
	/**
85
	 * Returns the specified setting's value as a string
86
	 * @param string $setting the setting
87
	 * @return string the value
88
	 */
89
	public static function getString($setting)
90
	{
91
		return (string)self::getValue($setting);
92
	}
93
94
	/**
95
	 * Returns the value for the specified setting. All settings are cached for 
96
	 * the duration of the request since this method can be called quite a lot.
97
	 * @param string $name the name of the setting
98
	 * @return mixed the setting value
99
	 * @throws InvalidRequestException if the specified setting doesn't exist
100
	 */
101
	private static function getValue($name)
102
	{
103
		if (self::$_settings === null)
0 ignored issues
show
The condition self::_settings === null is always false.
Loading history...
104
			self::$_settings = self::model()->findAll();
105
106
		foreach (self::$_settings as $setting)
107
			if ($setting->name == $name)
108
				return $setting->value;
109
			
110
		throw new InvalidRequestException();
111
	}
112
113
	/**
114
	 * Populates the model attributes
115
	 */
116
	protected function afterFind()
117
	{
118
		$definitions = $this->getDefinitions();
119
		if ($definitions[$this->name]['type'] === Setting::TYPE_CHECKBOX_LIST)
120
			$this->value = explode(',', $this->value);
0 ignored issues
show
Documentation Bug introduced by
It seems like explode(',', $this->value) of type string[] is incompatible with the declared type string of property $value.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
121
122
		$this->{$this->name} = $this->value;
123
124
		parent::afterFind();
125
	}
126
127
	/**
128
	 * Prepares the values to be saved
129
	 */
130
	protected function beforeSave()
131
	{
132
		if (is_array($this->value))
0 ignored issues
show
The condition is_array($this->value) is always false.
Loading history...
133
			$this->value = implode(',', $this->value);
134
135
		return parent::beforeSave();
136
	}
137
138
	/**
139
	 * @return array customized attribute labels (name=>label)
140
	 */
141
	public function attributeLabels()
142
	{
143
		$attributeLabels = array();
144
		$definitions = $this->getDefinitions();
145
146
		foreach($definitions as $setting => $definition)
147
			$attributeLabels[$setting] = $definition['label'];
148
149
		return $attributeLabels;
150
	}
151
152
	/**
153
	 * Returns the static model of the specified AR class.
154
	 * @param string $className active record class name.
155
	 * @return Settings the static model class
0 ignored issues
show
The type Settings was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
156
	 */
157
	public static function model($className = __CLASS__)
158
	{
159
		return parent::model($className);
0 ignored issues
show
Bug Best Practice introduced by
The expression return parent::model($className) returns the type CActiveRecord which is incompatible with the documented return type Settings.
Loading history...
160
	}
161
162
	/**
163
	 * @return string the associated database table name
164
	 */
165
	public function tableName()
166
	{
167
		return 'settings';
168
	}
169
170
	/**
171
	 * @return array the validation rules for this model
172
	 */
173
	public function rules()
174
	{
175
		return array(
176
			array('language, playlistFormat', 'required'),
177
			array('pagesize, requestTimeout', 'numerical', 'integerOnly'=>true, 'min'=>1),
178
			array('whitelist', 'validateWhitelist'),
179
		);
180
	}
181
182
	/**
183
	 * Validates the "whitelist" attribute. We consider it valid if it is 
184
	 * empty, if it is not we check if the definitions are legal. Additionally 
185
	 * we show a warning flash if the definitions would lead to the user being 
186
	 * locked out.
187
	 * @param string $attribute the attribute being validated
188
	 */
189
	public function validateWhitelist($attribute)
190
	{
191
		$definitions = $this->{$attribute};
192
		if (empty($definitions))
193
			return;
194
195
		$whitelist = Yii::app()->whitelist;
196
		$definitions = $whitelist->parseDefinitions($definitions);
197
198
		if (!$whitelist->validateDefinitions($definitions))
199
			$this->addError($attribute, Yii::t('Settings', 'Invalid whitelist definition'));
200
		else
201
		{
202
			$whitelist->setDefinitions($definitions);
203
			if (!$whitelist->check(true))
204
				Yii::app()->user->setFlash('warning', Yii::t('Settings', 'The specified whitelist restrictions will lock you out from this location'));
205
		}
206
	}
207
	
208
	/**
209
	 * Returns the settings definitions
210
	 * @return array
211
	 */
212
	public function getDefinitions()
213
	{
214
		return array(
215
			'language'=>array(
216
				'label'=>Yii::t('Settings', 'Application language'),
217
				'separator'=>array(
218
					'icon'=>'fa fa-pencil-square-o',
219
					'label'=>Yii::t('Settings', 'Look and feel'),
220
				),
221
				'type'=>self::TYPE_DROPDOWN,
222
				'default'=>'en',
223
				'description'=>Yii::t('Settings', 'Changing this will reset the default language for all users'),
224
				'listData'=>LanguageManager::getAvailableLanguages(),
225
				'order'=>50,
226
			),
227
			'applicationName'=>array(
228
				'label'=>Yii::t('Settings', 'Application name'),
229
				'type'=>self::TYPE_TEXT,
230
				'default'=>'XBMC Video Server',
231
				'order'=>100,
232
			),
233
			'applicationSubtitle'=>array(
234
				'label'=>Yii::t('Settings', 'Application subtitle'),
235
				'type'=>self::TYPE_TEXT,
236
				'default'=>Yii::t('Misc', 'Free your library'),
237
				'order'=>125,
238
			),
239
			'playlistFormat'=>array(
240
				'label'=>Yii::t('Settings', 'Playlist format'),
241
				'type'=>self::TYPE_DROPDOWN,
242
				'default'=>'m3u',
243
				'listData'=>PlaylistFactory::getTypes(),
244
				'order'=>150,
245
			),
246
			'singleFilePlaylist'=>array(
247
				'label'=>Yii::t('Settings', "Don't use playlists when item consists of a single file"),
248
				'type'=>self::TYPE_CHECKBOX,
249
				'default'=>'0',
250
				'description'=>Yii::t('Settings', 'You may have to right-click and copy the address in order to stream (not download) the file'),
251
				'order'=>200,
252
			),
253
			'showHelpBlocks'=>array(
254
				'label'=>Yii::t('Settings', 'Show help blocks throughout the site'),
255
				'type'=>self::TYPE_CHECKBOX,
256
				'default'=>'1',
257
				'order'=>300,
258
			),
259
			'pagesize'=>array(
260
				'label'=>Yii::t('Settings', 'Amount of results to show per page'),
261
				'type'=>self::TYPE_TEXT,
262
				'default'=>'60',
263
				'description'=>Yii::t('Settings', 'Leave empty to disable pagination altogether'),
264
				'htmlOptions'=>array(
265
					'span'=>1,
266
				),
267
				'order'=>500,
268
			),
269
			'ignoreArticle'=>array(
270
				'label'=>Yii::t('Settings', 'Ignore article ("the") in results'),
271
				'type'=>self::TYPE_CHECKBOX,
272
				'default'=>'',
273
				'order'=>550,
274
			),
275
			'requestTimeout'=>array(
276
				'label'=>Yii::t('Settings', 'Request timeout'),
277
				'separator'=>array(
278
					'icon'=>'fa fa-lock',
279
					'label'=>Yii::t('Settings', 'Security and performance')
280
				),
281
				'type'=>self::TYPE_TEXT,
282
				'default'=>'30',
283
				'description'=>Yii::t('Settings', 'Determines how long the application should wait for a response from XBMC. Increase this if you get timeout errors.'),
284
				'htmlOptions'=>array(
285
					'span'=>1,
286
				),
287
				'order'=>625,
288
			),
289
			'cacheApiCalls'=>array(
290
				'label'=>Yii::t('Settings', 'Cache all API results'),
291
				'type'=>self::TYPE_CHECKBOX,
292
				'default'=>'0',
293
				'description'=>Yii::t('Settings', 'Useful on slow hardware. A refresh button will appear in the menu which flushes the cache'),
294
				'order'=>650,
295
			),
296
			'enableActorTypeahead'=>array(
297
				'label'=>Yii::t('Settings', 'Enable auto-complete for actor names'),
298
				'type'=>self::TYPE_CHECKBOX,
299
				'default'=>'0',
300
				'description'=>Yii::t('Settings', 'Decreases performance, especially on large libraries and/or slow hardware'),
301
				'order'=>675,
302
			),
303
			'useHttpsForVfsUrls'=>array(
304
				'label'=>Yii::t('Settings', 'Use HTTPS when streaming'),
305
				'type'=>self::TYPE_CHECKBOX,
306
				'default'=>'0',
307
				'description'=>Yii::t('Settings', 'When checked, streaming will be done over HTTPS if the application is accessed over HTTPS. This will usually only work if the server uses a real signed certificate, thus it is not enabled by default.'),
308
				'order'=>700,
309
			),
310
			'allowUserPowerOff'=>array(
311
                                'label'=>Yii::t('Settings', 'Allow users to power off backends'),
312
                                'type'=>self::TYPE_CHECKBOX_LIST,
313
                                'default'=>'',
314
                                'listData'=>array(
315
                                        Setting::POWER_OPTION_SHUTDOWN=>Yii::t('Settings', 'Shutdown'),
316
                                        Setting::POWER_OPTION_SUSPEND=>Yii::t('Settings', 'Suspend'),
317
                                        Setting::POWER_OPTION_HIBERNATE=>Yii::t('Settings', 'Hibernate'),
318
                                        Setting::POWER_OPTION_REBOOT=>Yii::t('Settings', 'Reboot')),
319
				'description'=>Yii::t('Settings', 'Administrators are not affected by this setting and can always power off backends'),
320
                                'order'=>750,
321
                        ),
322
			'whitelist'=>array(
323
				'label'=>Yii::t('Settings', 'Access whitelist'),
324
				'type'=>self::TYPE_TEXT_WIDE,
325
				'default'=>'',
326
				'description'=>Yii::t('Settings', 'If specified, access is restricted to the defined whitelist. Valid values are IP addresses, IP subnets and domain names (including wildcards). Example: 192.168.1.0/24,1.2.3.4,example.com,*.user.com'),
327
				'order'=>800,
328
			),
329
		);
330
	}
331
332
}
333