Unyson - Version 2.3.1

Version Description

  • Fixed #566, #550
  • Fixed: Options default values not working in Customizer #410
Download this release

Release Info

Developer Unyson
Plugin Icon 128x128 Unyson
Version 2.3.1
Comparing to
See all releases

Code changes from version 2.3.0 to 2.3.1

framework/core/components/backend.php CHANGED
@@ -1718,12 +1718,10 @@ final class _FW_Component_Backend {
1718
  require_once fw_get_framework_directory('/includes/customizer/class--fw-customizer-control-option-wrapper.php');
1719
  }
1720
 
1721
- $option_defaults = fw()->backend->option_type($opt['option']['type'])->get_defaults();
1722
-
1723
  $wp_customize->add_setting(
1724
  $setting_id,
1725
  array(
1726
- 'default' => $option_defaults['value'],
1727
 
1728
  // added later because we can't create control first without an existing setting
1729
  //'sanitize_callback' => array($control, 'setting_sanitize_callback'),
1718
  require_once fw_get_framework_directory('/includes/customizer/class--fw-customizer-control-option-wrapper.php');
1719
  }
1720
 
 
 
1721
  $wp_customize->add_setting(
1722
  $setting_id,
1723
  array(
1724
+ 'default' => fw()->backend->option_type($opt['option']['type'])->get_value_from_input($opt['option'], null),
1725
 
1726
  // added later because we can't create control first without an existing setting
1727
  //'sanitize_callback' => array($control, 'setting_sanitize_callback'),
framework/helpers/database.php CHANGED
@@ -391,44 +391,44 @@
391
  * @return mixed|null
392
  */
393
  function fw_get_db_customizer_option( $option_id = null, $default_value = null ) {
394
- $value = get_theme_mod(FW_Option_Type::get_default_name_prefix(), array());
395
-
396
- if (!is_null($option_id)) {
397
- $value = fw_akg($option_id, $value, $default_value);
398
- }
399
-
400
- if (
401
- (!is_null($option_id) && is_null($value)) // a specific option_id was requested
402
- ||
403
- (is_null($option_id) && empty($value)) // all options were requested but the db value is empty (this can happen after Reset)
404
- ) {
405
- /**
406
- * Maybe the options was never saved or the given option id does not exist
407
- * Extract the default values from the options array and try to find there the option id
408
- */
409
 
 
 
410
  $cache_key = 'fw_default_options_values/customizer';
411
 
412
  try {
413
- $all_options_values = FW_Cache::get( $cache_key );
414
  } catch ( FW_Cache_Not_Found_Exception $e ) {
415
  // extract the default values from options array
416
- $all_options_values = fw_get_options_values_from_input(
417
  fw()->theme->get_customizer_options(),
418
  array()
419
  );
420
 
421
- FW_Cache::set( $cache_key, $all_options_values );
422
  }
 
423
 
424
- if ( empty( $option_id ) ) {
425
- // option id not specified, return all options values
426
- return $all_options_values;
427
- } else {
428
- return fw_akg( $option_id, $all_options_values, $default_value );
429
- }
430
  } else {
431
- return $value;
 
 
 
 
 
 
 
 
 
 
 
432
  }
433
  }
434
 
391
  * @return mixed|null
392
  */
393
  function fw_get_db_customizer_option( $option_id = null, $default_value = null ) {
394
+ // note: this contains only changed controls/options
395
+ $all_db_values = get_theme_mod(FW_Option_Type::get_default_name_prefix(), array());
 
 
 
 
 
 
 
 
 
 
 
 
 
396
 
397
+ // extract options default values
398
+ {
399
  $cache_key = 'fw_default_options_values/customizer';
400
 
401
  try {
402
+ $all_default_values = FW_Cache::get( $cache_key );
403
  } catch ( FW_Cache_Not_Found_Exception $e ) {
404
  // extract the default values from options array
405
+ $all_default_values = fw_get_options_values_from_input(
406
  fw()->theme->get_customizer_options(),
407
  array()
408
  );
409
 
410
+ FW_Cache::set( $cache_key, $all_default_values );
411
  }
412
+ }
413
 
414
+ if (is_null($option_id)) {
415
+ return array_merge(
416
+ $all_default_values,
417
+ $all_db_values
418
+ );
 
419
  } else {
420
+ $base_key = explode('/', $option_id); // note: option_id can be a multi-key 'a/b/c'
421
+ $base_key = array_shift($base_key);
422
+
423
+ $all_db_values = array_key_exists($base_key, $all_db_values)
424
+ ? $all_db_values
425
+ : $all_default_values;
426
+
427
+ return fw_akg(
428
+ $option_id,
429
+ $all_db_values,
430
+ $default_value
431
+ );
432
  }
433
  }
434
 
framework/includes/option-types/map/class-fw-option-type-map.php CHANGED
@@ -23,11 +23,10 @@ class FW_Option_Type_Map extends FW_Option_Type {
23
  * @internal
24
  * {@inheritdoc}
25
  */
26
- protected function _enqueue_static($id, $option, $data)
27
- {
28
  wp_enqueue_style(
29
  $this->get_type() . '-styles',
30
- fw_get_framework_directory_uri('/includes/option-types/' . $this->get_type() . '/static/css/style.css')
31
  );
32
 
33
  wp_enqueue_script(
@@ -39,7 +38,7 @@ class FW_Option_Type_Map extends FW_Option_Type {
39
  );
40
  wp_enqueue_script(
41
  $this->get_type() . '-styles',
42
- fw_get_framework_directory_uri('/includes/option-types/' . $this->get_type() . '/static/js/scripts.js'),
43
  array( 'jquery', 'jquery-ui-widget', 'fw-events', 'underscore', 'jquery-ui-autocomplete' ),
44
  '1.0',
45
  true
@@ -50,9 +49,11 @@ class FW_Option_Type_Map extends FW_Option_Type {
50
  * @internal
51
  */
52
  protected function _render( $id, $option, $data ) {
53
- $data['value']['coordinates'] = json_encode($data['value']['coordinates']);
 
 
54
 
55
- $path = fw_get_framework_directory('/includes/option-types/' . $this->get_type() . '/views/view.php');
56
 
57
  return fw_render_view( $path, array(
58
  'id' => $id,
@@ -65,15 +66,8 @@ class FW_Option_Type_Map extends FW_Option_Type {
65
  * @internal
66
  */
67
  protected function _get_value_from_input( $option, $input_value ) {
68
- $coordinates = array(
69
- 'lat' => - 34,
70
- 'lng' => 150
71
- );
72
- if ( is_array( $input_value ) ) {
73
- if ( $input_value['coordinates'] ) {
74
- $coordinates = json_decode( $input_value['coordinates'], true );
75
- }
76
- } else {
77
  $input_value = $option['value'];
78
  }
79
 
@@ -85,7 +79,11 @@ class FW_Option_Type_Map extends FW_Option_Type {
85
  'state' => ( isset ( $input_value['state'] ) ) ? $input_value['state'] : '',
86
  'country' => ( isset ( $input_value['country'] ) ) ? $input_value['country'] : '',
87
  'zip' => ( isset ( $input_value['zip'] ) ) ? $input_value['zip'] : '',
88
- 'coordinates' => $coordinates
 
 
 
 
89
  );
90
 
91
  return $location;
@@ -98,8 +96,8 @@ class FW_Option_Type_Map extends FW_Option_Type {
98
  return array(
99
  'value' => array(
100
  'coordinates' => array(
101
- 'lat' => -34,
102
- 'lng' => 150,
103
  )
104
  )
105
  );
23
  * @internal
24
  * {@inheritdoc}
25
  */
26
+ protected function _enqueue_static( $id, $option, $data ) {
 
27
  wp_enqueue_style(
28
  $this->get_type() . '-styles',
29
+ fw_get_framework_directory_uri( '/includes/option-types/' . $this->get_type() . '/static/css/style.css' )
30
  );
31
 
32
  wp_enqueue_script(
38
  );
39
  wp_enqueue_script(
40
  $this->get_type() . '-styles',
41
+ fw_get_framework_directory_uri( '/includes/option-types/' . $this->get_type() . '/static/js/scripts.js' ),
42
  array( 'jquery', 'jquery-ui-widget', 'fw-events', 'underscore', 'jquery-ui-autocomplete' ),
43
  '1.0',
44
  true
49
  * @internal
50
  */
51
  protected function _render( $id, $option, $data ) {
52
+ $data['value']['coordinates'] = isset( $data['value']['coordinates'] )
53
+ ? json_encode($data['value']['coordinates'])
54
+ : '';
55
 
56
+ $path = fw_get_framework_directory( '/includes/option-types/' . $this->get_type() . '/views/view.php' );
57
 
58
  return fw_render_view( $path, array(
59
  'id' => $id,
66
  * @internal
67
  */
68
  protected function _get_value_from_input( $option, $input_value ) {
69
+
70
+ if ( ! is_array( $input_value ) || empty( $input_value ) ) {
 
 
 
 
 
 
 
71
  $input_value = $option['value'];
72
  }
73
 
79
  'state' => ( isset ( $input_value['state'] ) ) ? $input_value['state'] : '',
80
  'country' => ( isset ( $input_value['country'] ) ) ? $input_value['country'] : '',
81
  'zip' => ( isset ( $input_value['zip'] ) ) ? $input_value['zip'] : '',
82
+ 'coordinates' => ( isset ( $input_value['coordinates'] ) )
83
+ ? ( is_array($input_value['coordinates']) )
84
+ ? $input_value['coordinates']
85
+ : json_decode($input_value['coordinates'])
86
+ : ''
87
  );
88
 
89
  return $location;
96
  return array(
97
  'value' => array(
98
  'coordinates' => array(
99
+ 'lat' => - 34,
100
+ 'lng' => 150,
101
  )
102
  )
103
  );
framework/includes/option-types/simple.php CHANGED
@@ -1,15 +1,14 @@
1
- <?php if (!defined('FW')) die('Forbidden');
 
 
2
 
3
  /**
4
  * Simple option types (without scripts, styles or views)
5
  *
6
  * Convention: Simple options like text|select|input|textarea, should always generate only input, without div wrappers
7
  */
8
-
9
- class FW_Option_Type_Hidden extends FW_Option_Type
10
- {
11
- public function get_type()
12
- {
13
  return 'hidden';
14
  }
15
 
@@ -17,50 +16,57 @@ class FW_Option_Type_Hidden extends FW_Option_Type
17
  * @internal
18
  * {@inheritdoc}
19
  */
20
- protected function _enqueue_static($id, $option, $data) {}
 
21
 
22
  /**
 
 
 
 
 
 
23
  * @internal
24
  */
25
- protected function _render($id, $option, $data)
26
- {
27
- $option['attr']['value'] = (string)$data['value'];
28
 
29
- return '<input '. fw_attr_to_html($option['attr']) .' type="hidden" />';
30
  }
31
 
32
  /**
 
 
 
 
 
33
  * @internal
34
  */
35
- protected function _get_value_from_input($option, $input_value)
36
- {
37
- return (string)(is_null($input_value) ? $option['value'] : $input_value);
38
  }
39
 
40
  /**
41
  * @internal
42
  */
43
- public function _get_backend_width_type()
44
- {
45
  return 'auto';
46
  }
47
 
48
  /**
49
  * @internal
50
  */
51
- protected function _get_defaults()
52
- {
53
  return array(
54
  'value' => ''
55
  );
56
  }
57
  }
58
- FW_Option_Type::register('FW_Option_Type_Hidden');
59
 
60
- class FW_Option_Type_Text extends FW_Option_Type
61
- {
62
- public function get_type()
63
- {
64
  return 'text';
65
  }
66
 
@@ -68,70 +74,81 @@ class FW_Option_Type_Text extends FW_Option_Type
68
  * @internal
69
  * {@inheritdoc}
70
  */
71
- protected function _enqueue_static($id, $option, $data) {}
 
72
 
73
  /**
 
 
 
 
 
 
74
  * @internal
75
  */
76
- protected function _render($id, $option, $data)
77
- {
78
- $option['attr']['value'] = (string)$data['value'];
79
 
80
- return '<input '. fw_attr_to_html($option['attr']) .' type="text" />';
81
  }
82
 
83
  /**
 
 
 
 
 
84
  * @internal
85
  */
86
- protected function _get_value_from_input($option, $input_value)
87
- {
88
- return (string)(is_null($input_value) ? $option['value'] : $input_value);
89
  }
90
 
91
  /**
92
  * @internal
93
  */
94
- protected function _get_defaults()
95
- {
96
  return array(
97
  'value' => ''
98
  );
99
  }
100
  }
101
- FW_Option_Type::register('FW_Option_Type_Text');
102
 
103
- class FW_Option_Type_Short_Text extends FW_Option_Type_Text
104
- {
105
- public function get_type()
106
- {
107
  return 'short-text';
108
  }
109
 
110
  /**
 
 
 
 
 
 
111
  * @internal
112
  */
113
- protected function _render($id, $option, $data)
114
- {
115
  $option['attr']['class'] .= ' fw-option-width-short';
116
 
117
- return parent::_render($id, $option, $data);
118
  }
119
 
120
  /**
121
  * {@inheritdoc}
122
  * @internal
123
  */
124
- public function _get_backend_width_type()
125
- {
126
  return 'auto';
127
  }
128
  }
129
- FW_Option_Type::register('FW_Option_Type_Short_Text');
130
 
131
- class FW_Option_Type_Password extends FW_Option_Type
132
- {
133
- public function get_type()
134
- {
135
  return 'password';
136
  }
137
 
@@ -139,42 +156,50 @@ class FW_Option_Type_Password extends FW_Option_Type
139
  * @internal
140
  * {@inheritdoc}
141
  */
142
- protected function _enqueue_static($id, $option, $data) {}
 
143
 
144
  /**
 
 
 
 
 
 
145
  * @internal
146
  */
147
- protected function _render($id, $option, $data)
148
- {
149
- $option['attr']['value'] = (string)$data['value'];
150
 
151
- return '<input '. fw_attr_to_html($option['attr']) .' type="password" />';
152
  }
153
 
154
  /**
 
 
 
 
 
155
  * @internal
156
  */
157
- protected function _get_value_from_input($option, $input_value)
158
- {
159
- return (string)(is_null($input_value) ? $option['value'] : $input_value);
160
  }
161
 
162
  /**
163
  * @internal
164
  */
165
- protected function _get_defaults()
166
- {
167
  return array(
168
  'value' => ''
169
  );
170
  }
171
  }
172
- FW_Option_Type::register('FW_Option_Type_Password');
173
 
174
- class FW_Option_Type_Textarea extends FW_Option_Type
175
- {
176
- public function get_type()
177
- {
178
  return 'textarea';
179
  }
180
 
@@ -182,49 +207,57 @@ class FW_Option_Type_Textarea extends FW_Option_Type
182
  * @internal
183
  * {@inheritdoc}
184
  */
185
- protected function _enqueue_static($id, $option, $data) {}
 
186
 
187
  /**
 
 
 
 
 
 
188
  * @internal
189
  */
190
- protected function _render($id, $option, $data)
191
- {
192
- $option['value'] = (string)$data['value'];
193
 
194
- unset($option['attr']['value']); // be sure to remove value from attributes
195
 
196
- $option['attr'] = array_merge(array('rows' => '6'), $option['attr']);
197
  $option['attr']['class'] .= ' code';
198
 
199
- return '<textarea '. fw_attr_to_html($option['attr']) .'>'.
200
- htmlspecialchars($option['value'], ENT_COMPAT, 'UTF-8').
201
- '</textarea>';
202
  }
203
 
204
  /**
 
 
 
 
 
205
  * @internal
206
  */
207
- protected function _get_value_from_input($option, $input_value)
208
- {
209
- return (string)(is_null($input_value) ? $option['value'] : $input_value);
210
  }
211
 
212
  /**
213
  * @internal
214
  */
215
- protected function _get_defaults()
216
- {
217
  return array(
218
  'value' => ''
219
  );
220
  }
221
  }
222
- FW_Option_Type::register('FW_Option_Type_Textarea');
223
 
224
- class FW_Option_Type_Html extends FW_Option_Type
225
- {
226
- public function get_type()
227
- {
228
  return 'html';
229
  }
230
 
@@ -232,108 +265,111 @@ class FW_Option_Type_Html extends FW_Option_Type
232
  * @internal
233
  * {@inheritdoc}
234
  */
235
- protected function _enqueue_static($id, $option, $data) {}
 
236
 
237
  /**
 
 
 
 
 
 
238
  * @internal
239
  */
240
- protected function _render($id, $option, $data)
241
- {
242
- $option['attr']['value'] = (string)$data['value'];
243
 
244
  $div_attr = $option['attr'];
245
- unset($div_attr['name']);
246
- unset($div_attr['value']);
247
 
248
- return '<div '. fw_attr_to_html($div_attr) .'>'.
249
- fw()->backend->option_type('hidden')->render($id, array(
250
- 'attr' => array(
251
- 'class' => 'fw-option-html-value',
252
- ),
253
- 'value' => $option['attr']['value'],
254
- ),
255
- array(
256
- 'id_prefix' => $data['id_prefix'],
257
- 'name_prefix' => $data['name_prefix']
258
- )
259
- ).
260
- '<div class="fw-option-html">'. $option['html'] .'</div>'.
261
- '</div>';
262
  }
263
 
264
  /**
 
 
 
 
 
265
  * @internal
266
  */
267
- protected function _get_value_from_input($option, $input_value)
268
- {
269
- return (string)(is_null($input_value) ? $option['value'] : $input_value);
270
  }
271
 
272
  /**
273
  * @internal
274
  */
275
- public function _get_backend_width_type()
276
- {
277
  return 'auto';
278
  }
279
 
280
  /**
281
  * @internal
282
  */
283
- protected function _get_defaults()
284
- {
285
  return array(
286
  'value' => '',
287
  'html' => '<em>default html</em>',
288
  );
289
  }
290
  }
291
- FW_Option_Type::register('FW_Option_Type_Html');
 
292
 
293
  /**
294
  * Same html but displayed in fixed width
295
  */
296
- class FW_Option_Type_Html_Fixed extends FW_Option_Type_Html
297
- {
298
- public function get_type()
299
- {
300
  return 'html-fixed';
301
  }
302
 
303
  /**
304
  * @internal
305
  */
306
- public function _get_backend_width_type()
307
- {
308
  return 'fixed';
309
  }
310
  }
311
- FW_Option_Type::register('FW_Option_Type_Html_Fixed');
 
312
 
313
  /**
314
  * Same html but displayed in full width
315
  */
316
- class FW_Option_Type_Html_Full extends FW_Option_Type_Html
317
- {
318
- public function get_type()
319
- {
320
  return 'html-full';
321
  }
322
 
323
  /**
324
  * @internal
325
  */
326
- public function _get_backend_width_type()
327
- {
328
  return 'full';
329
  }
330
  }
331
- FW_Option_Type::register('FW_Option_Type_Html_Full');
332
 
333
- class FW_Option_Type_Checkbox extends FW_Option_Type
334
- {
335
- public function get_type()
336
- {
337
  return 'checkbox';
338
  }
339
 
@@ -341,63 +377,70 @@ class FW_Option_Type_Checkbox extends FW_Option_Type
341
  * @internal
342
  * {@inheritdoc}
343
  */
344
- protected function _enqueue_static($id, $option, $data) {}
 
345
 
346
  /**
 
 
 
 
 
 
347
  * @internal
348
  */
349
- protected function _render($id, $option, $data)
350
- {
351
- $option['value'] = (bool)$data['value'];
352
 
353
- unset($option['attr']['value']);
354
 
355
- return '<input type="checkbox" name="'. esc_attr($option['attr']['name']) .'" value="" checked="checked" style="display: none">'.
356
- '<!-- used for "'. esc_attr($id) .'" to be present in _POST -->'.
357
- ''.
358
- '<label for="'. esc_attr($option['attr']['id']) .'">'.
359
- '<input '. fw_attr_to_html($option['attr']) .' type="checkbox" value="true" '.
360
- ($option['value'] ? 'checked="checked" ' : '').
361
- '> '. htmlspecialchars($option['text'], ENT_COMPAT, 'UTF-8').
362
- '</label>';
363
  }
364
 
365
  /**
 
 
 
 
 
366
  * @internal
367
  */
368
- protected function _get_value_from_input($option, $input_value)
369
- {
370
- return (bool)(is_null($input_value) ? $option['value'] : $input_value);
371
  }
372
 
373
  /**
374
  * @internal
375
  */
376
- public function _get_backend_width_type()
377
- {
378
  return 'auto';
379
  }
380
 
381
  /**
382
  * @internal
383
  */
384
- protected function _get_defaults()
385
- {
386
  return array(
387
  'value' => false,
388
- 'text' => __('Yes', 'fw'),
389
  );
390
  }
391
  }
392
- FW_Option_Type::register('FW_Option_Type_Checkbox');
 
393
 
394
  /**
395
  * Checkboxes list
396
  */
397
- class FW_Option_Type_Checkboxes extends FW_Option_Type
398
- {
399
- public function get_type()
400
- {
401
  return 'checkboxes';
402
  }
403
 
@@ -405,41 +448,47 @@ class FW_Option_Type_Checkboxes extends FW_Option_Type
405
  * @internal
406
  * {@inheritdoc}
407
  */
408
- protected function _enqueue_static($id, $option, $data) {}
 
409
 
410
  /**
 
 
 
 
 
 
411
  * @internal
412
  */
413
- protected function _render($id, $option, $data)
414
- {
415
- $option['value'] = is_array($data['value']) ? $data['value'] : array();
416
 
417
  $div_attr = $option['attr'];
418
- unset($div_attr['name']);
419
- unset($div_attr['value']);
420
 
421
- if ( $option['inline'] ) {
422
  $div_attr['class'] .= ' fw-option-type-checkboxes-inline fw-clearfix';
423
  }
424
 
425
- $html = '<div '. fw_attr_to_html($div_attr) .'>';
426
 
427
- $html .= '<input type="checkbox" name="'. esc_attr($option['attr']['name']) .'[]" value="" checked="checked" style="display: none">'.
428
- '<!-- used for "'. esc_attr($id) .'" to be present in _POST -->';
429
 
430
- foreach ($option['choices'] as $value => $text) {
431
- $choice_id = $option['attr']['id'] .'-'. $value;
432
 
433
- $html .= '<div>'.
434
- '<label for="'. esc_attr($choice_id) .'">'.
435
- '<input type="checkbox" '.
436
- 'name="'. esc_attr($option['attr']['name']) .'['. esc_attr($value) .']" '.
437
- 'value="true" '.
438
- 'id="'. esc_attr($choice_id) .'" '.
439
- (isset($option['value'][$value]) && $option['value'][$value] ? 'checked="checked" ' : '').
440
- '> '. htmlspecialchars($text, ENT_COMPAT, 'UTF-8').
441
- '</label>'.
442
- '</div>';
443
  }
444
 
445
  $html .= '</div>';
@@ -448,21 +497,27 @@ class FW_Option_Type_Checkboxes extends FW_Option_Type
448
  }
449
 
450
  /**
 
 
 
 
 
451
  * @internal
452
  */
453
- protected function _get_value_from_input($option, $input_value)
454
- {
455
- if (is_array($input_value)) {
456
  $value = array();
457
 
458
- foreach ($input_value as $choice => $val) {
459
- if ($val === '')
460
  continue;
 
461
 
462
- if (!isset($option['choices'][$choice]))
463
  continue;
 
464
 
465
- $value[$choice] = true;
466
  }
467
  } else {
468
  $value = $option['value'];
@@ -474,16 +529,14 @@ class FW_Option_Type_Checkboxes extends FW_Option_Type
474
  /**
475
  * @internal
476
  */
477
- public function _get_backend_width_type()
478
- {
479
  return 'auto';
480
  }
481
 
482
  /**
483
  * @internal
484
  */
485
- protected function _get_defaults()
486
- {
487
  return array(
488
  'inline' => false, // Set this parameter to true in case you want all checkbox inputs to be rendered inline
489
  'value' => array(),
@@ -491,15 +544,14 @@ class FW_Option_Type_Checkboxes extends FW_Option_Type
491
  );
492
  }
493
  }
494
- FW_Option_Type::register('FW_Option_Type_Checkboxes');
 
495
 
496
  /**
497
  * Radio list
498
  */
499
- class FW_Option_Type_Radio extends FW_Option_Type
500
- {
501
- public function get_type()
502
- {
503
  return 'radio';
504
  }
505
 
@@ -507,38 +559,44 @@ class FW_Option_Type_Radio extends FW_Option_Type
507
  * @internal
508
  * {@inheritdoc}
509
  */
510
- protected function _enqueue_static($id, $option, $data) {}
 
511
 
512
  /**
 
 
 
 
 
 
513
  * @internal
514
  */
515
- protected function _render($id, $option, $data)
516
- {
517
- $option['value'] = (string)$data['value'];
518
 
519
  $div_attr = $option['attr'];
520
- unset($div_attr['name']);
521
- unset($div_attr['value']);
522
 
523
- if ( $option['inline'] ) {
524
  $div_attr['class'] .= ' fw-option-type-radio-inline fw-clearfix';
525
  }
526
 
527
- $html = '<div '. fw_attr_to_html($div_attr) .'>';
528
-
529
- foreach ($option['choices'] as $value => $text) {
530
- $choice_id = $option['attr']['id'] .'-'. $value;
531
-
532
- $html .= '<div>'.
533
- '<label for="'. esc_attr($choice_id) .'">'.
534
- '<input type="radio" '.
535
- 'name="'. esc_attr($option['attr']['name']) .'" '.
536
- 'value="'. esc_attr($value) .'" '.
537
- 'id="'. esc_attr($choice_id) .'" '.
538
- ($option['value'] == $value ? 'checked="checked" ' : '').
539
- '> '. htmlspecialchars($text, ENT_COMPAT, 'UTF-8').
540
- '</label>'.
541
- '</div>';
542
  }
543
 
544
  $html .= '</div>';
@@ -547,54 +605,55 @@ class FW_Option_Type_Radio extends FW_Option_Type
547
  }
548
 
549
  /**
 
 
 
 
 
550
  * @internal
551
  */
552
- protected function _get_value_from_input($option, $input_value)
553
- {
554
- if (!isset($option['choices'][$input_value])) {
555
  if (
556
- empty($option['choices']) ||
557
- isset($option['choices'][ $option['value'] ])
558
  ) {
559
  $input_value = $option['value'];
560
  } else {
561
- reset($option['choices']);
562
- $input_value = key($option['choices']);
563
  }
564
  }
565
 
566
- return (string)$input_value;
567
  }
568
 
569
  /**
570
  * @internal
571
  */
572
- public function _get_backend_width_type()
573
- {
574
  return 'auto';
575
  }
576
 
577
  /**
578
  * @internal
579
  */
580
- protected function _get_defaults()
581
- {
582
  return array(
583
- 'inline' => false, // Set this parameter to true in case you want all radio inputs to be rendered inline
584
  'value' => '',
585
  'choices' => array()
586
  );
587
  }
588
  }
589
- FW_Option_Type::register('FW_Option_Type_Radio');
 
590
 
591
  /**
592
  * Select
593
  */
594
- class FW_Option_Type_Select extends FW_Option_Type
595
- {
596
- public function get_type()
597
- {
598
  return 'select';
599
  }
600
 
@@ -602,13 +661,19 @@ class FW_Option_Type_Select extends FW_Option_Type
602
  * @internal
603
  * {@inheritdoc}
604
  */
605
- protected function _enqueue_static($id, $option, $data) {}
 
606
 
607
  /**
 
 
 
 
 
 
608
  * @internal
609
  */
610
- protected function _render($id, $option, $data)
611
- {
612
  $option['value'] = $data['value'];
613
 
614
  $option['attr']['data-saved-value'] = $data['value'];
@@ -617,98 +682,107 @@ class FW_Option_Type_Select extends FW_Option_Type
617
  $option['attr']['multiple']
618
  );
619
 
620
- if (!isset($option['choices'])) {
621
  $option['choices'] = array();
622
  }
623
 
624
- $html = '<select '. fw_attr_to_html($option['attr']) .'>'.
625
- $this->render_choices($option['choices'], $option['value']).
626
- '</select>';
627
 
628
  return $html;
629
  }
630
 
631
  /**
 
 
 
 
 
632
  * @internal
633
  */
634
- protected function _get_value_from_input($option, $input_value)
635
- {
636
- if (is_null($input_value)) {
637
  return $option['value'];
638
  }
639
 
640
- if (empty($option['no-validate'])) {
641
- $all_choices = $this->get_choices($option['choices']);
642
 
643
- if (!isset($all_choices[$input_value])) {
644
  if (
645
- empty($all_choices) ||
646
- isset($all_choices[ $option['value'] ])
647
  ) {
648
  $input_value = $option['value'];
649
  } else {
650
- reset($all_choices);
651
- $input_value = key($all_choices);
652
  }
653
  }
654
 
655
- unset($all_choices);
656
  }
657
 
658
- return (string)$input_value;
659
  }
660
 
661
  /**
662
  * Extract recursive from optgroups all choices as one level array
 
 
 
 
 
 
663
  */
664
- protected function get_choices($choices)
665
- {
666
  $result = array();
667
 
668
- foreach ($choices as $cid => $choice) {
669
- if (is_array($choice) && isset($choice['choices'])) {
670
  // optgroup
671
- $result += $this->get_choices($choice['choices']);
672
  } else {
673
- $result[$cid] = $choice;
674
  }
675
  }
676
 
677
  return $result;
678
  }
679
 
680
- protected function render_choices(&$choices, &$value)
681
- {
682
- if (empty($choices) || !is_array($choices))
683
  return '';
 
684
 
685
  $html = '';
686
 
687
- foreach ($choices as $c_value => $choice) {
688
- if (is_array($choice)) {
689
- if (!isset($choice['attr'])) {
690
  $choice['attr'] = array();
691
  }
692
 
693
- if (isset($choice['choices'])) { // optgroup
694
- $html .= '<optgroup '. fw_attr_to_html($choice['attr']) .'>'.
695
- $this->render_choices($choice['choices'], $value).
696
- '</optgroup>';
697
  } else { // choice as array (with custom attributes)
698
  $choice['attr']['value'] = $c_value;
699
 
700
- unset($choice['attr']['selected']); // this is not allowed
701
 
702
- $html .= '<option '. fw_attr_to_html($choice['attr']) .' '.
703
- ($c_value == $value ? 'selected="selected" ' : '') .'>'.
704
- htmlspecialchars(isset($choice['text']) ? $choice['text'] : '', ENT_COMPAT, 'UTF-8').
705
- '</option>';
706
  }
707
  } else { // simple choice
708
- $html .= '<option value="'. esc_attr($c_value) .'" '.
709
- ($c_value == $value ? 'selected="selected" ' : '') .'>'.
710
- htmlspecialchars($choice, ENT_COMPAT, 'UTF-8').
711
- '</option>';
712
  }
713
  }
714
 
@@ -718,51 +792,52 @@ class FW_Option_Type_Select extends FW_Option_Type
718
  /**
719
  * @internal
720
  */
721
- protected function _get_defaults()
722
- {
723
  return array(
724
  'value' => '',
725
  'choices' => array()
726
  );
727
  }
728
  }
729
- FW_Option_Type::register('FW_Option_Type_Select');
730
 
731
- class FW_Option_Type_Short_Select extends FW_Option_Type_Select
732
- {
733
- public function get_type()
734
- {
735
  return 'short-select';
736
  }
737
 
738
  /**
 
 
 
 
 
 
739
  * @internal
740
  */
741
- protected function _render($id, $option, $data)
742
- {
743
  $option['attr']['class'] .= ' fw-option-width-short';
744
 
745
- return parent::_render($id, $option, $data);
746
  }
747
 
748
  /**
749
  * {@inheritdoc}
750
  * @internal
751
  */
752
- public function _get_backend_width_type()
753
- {
754
  return 'auto';
755
  }
756
  }
757
- FW_Option_Type::register('FW_Option_Type_Short_Select');
 
758
 
759
  /**
760
  * Select Multiple
761
  */
762
- class FW_Option_Type_Select_Multiple extends FW_Option_Type_Select
763
- {
764
- public function get_type()
765
- {
766
  return 'select-multiple';
767
  }
768
 
@@ -770,87 +845,103 @@ class FW_Option_Type_Select_Multiple extends FW_Option_Type_Select
770
  * @internal
771
  * {@inheritdoc}
772
  */
773
- protected function _enqueue_static($id, $option, $data) {}
 
774
 
775
  /**
 
 
 
 
 
 
776
  * @internal
777
  */
778
- protected function _render($id, $option, $data)
779
- {
780
  $option['value'] = $data['value'];
781
 
782
- unset($option['attr']['value']);
 
 
783
 
784
  $option['attr']['name'] .= '[]';
785
  $option['attr']['multiple'] = 'multiple';
786
 
787
- if (!isset($option['attr']['size'])) {
788
  $option['attr']['size'] = '7';
789
  }
790
 
791
- $html = '<select '. fw_attr_to_html($option['attr']) .'>'.
792
- $this->render_choices($option['choices'], $option['value']).
793
- '</select>';
794
 
795
  return $html;
796
  }
797
 
798
  /**
 
 
 
 
 
799
  * @internal
800
  */
801
- protected function _get_value_from_input($option, $input_value)
802
- {
803
- if (!is_array($input_value)) {
804
  $input_value = $option['value'];
805
  }
806
 
807
- if (empty($option['no-validate'])) {
808
- $all_choices = $this->get_choices($option['choices']);
 
 
 
 
809
 
810
- foreach ($input_value as $key => $value) {
811
- if (!isset($all_choices[$value])) {
812
- unset($input_value[$key]);
813
  }
814
  }
815
 
816
- unset($all_choices);
817
  }
818
 
819
  return $input_value;
820
  }
821
 
822
- protected function render_choices(&$choices, &$value)
823
- {
824
- if (empty($choices) || !is_array($choices))
825
  return '';
 
826
 
827
  $html = '';
828
 
829
- foreach ($choices as $c_value => $choice) {
830
- if (is_array($choice)) {
831
- if (!isset($choice['attr'])) {
832
  $choice['attr'] = array();
833
  }
834
 
835
- if (isset($choice['choices'])) { // optgroup
836
- $html .= '<optgroup '. fw_attr_to_html($choice['attr']) .'>'.
837
- $this->render_choices($choice['choices'], $value).
838
- '</optgroup>';
839
  } else { // choice as array (with custom attributes)
840
  $choice['attr']['value'] = $c_value;
841
 
842
- unset($choice['attr']['selected']); // this is not allowed
843
 
844
- $html .= '<option '. fw_attr_to_html($choice['attr']) .' '.
845
- (in_array($c_value, $value) ? 'selected="selected" ' : '') .'>'.
846
- htmlspecialchars(isset($choice['text']) ? $choice['text'] : '', ENT_COMPAT, 'UTF-8').
847
- '</option>';
848
  }
849
  } else { // simple choice
850
- $html .= '<option value="'. esc_attr($c_value) .'" '.
851
- (in_array($c_value, $value) ? 'selected="selected" ' : '') .'>'.
852
- htmlspecialchars($choice, ENT_COMPAT, 'UTF-8').
853
- '</option>';
854
  }
855
  }
856
 
@@ -860,12 +951,12 @@ class FW_Option_Type_Select_Multiple extends FW_Option_Type_Select
860
  /**
861
  * @internal
862
  */
863
- protected function _get_defaults()
864
- {
865
  return array(
866
  'value' => array(),
867
  'choices' => array()
868
  );
869
  }
870
  }
871
- FW_Option_Type::register('FW_Option_Type_Select_Multiple');
 
1
+ <?php if ( ! defined( 'FW' ) ) {
2
+ die( 'Forbidden' );
3
+ }
4
 
5
  /**
6
  * Simple option types (without scripts, styles or views)
7
  *
8
  * Convention: Simple options like text|select|input|textarea, should always generate only input, without div wrappers
9
  */
10
+ class FW_Option_Type_Hidden extends FW_Option_Type {
11
+ public function get_type() {
 
 
 
12
  return 'hidden';
13
  }
14
 
16
  * @internal
17
  * {@inheritdoc}
18
  */
19
+ protected function _enqueue_static( $id, $option, $data ) {
20
+ }
21
 
22
  /**
23
+ * @param string $id
24
+ * @param array $option
25
+ * @param array $data
26
+ *
27
+ * @return string
28
+ *
29
  * @internal
30
  */
31
+ protected function _render( $id, $option, $data ) {
32
+ $option['attr']['value'] = (string) $data['value'];
 
33
 
34
+ return '<input ' . fw_attr_to_html( $option['attr'] ) . ' type="hidden" />';
35
  }
36
 
37
  /**
38
+ * @param array $option
39
+ * @param array|null|string $input_value
40
+ *
41
+ * @return string
42
+ *
43
  * @internal
44
  */
45
+ protected function _get_value_from_input( $option, $input_value ) {
46
+ return (string) ( is_null( $input_value ) ? $option['value'] : $input_value );
 
47
  }
48
 
49
  /**
50
  * @internal
51
  */
52
+ public function _get_backend_width_type() {
 
53
  return 'auto';
54
  }
55
 
56
  /**
57
  * @internal
58
  */
59
+ protected function _get_defaults() {
 
60
  return array(
61
  'value' => ''
62
  );
63
  }
64
  }
 
65
 
66
+ FW_Option_Type::register( 'FW_Option_Type_Hidden' );
67
+
68
+ class FW_Option_Type_Text extends FW_Option_Type {
69
+ public function get_type() {
70
  return 'text';
71
  }
72
 
74
  * @internal
75
  * {@inheritdoc}
76
  */
77
+ protected function _enqueue_static( $id, $option, $data ) {
78
+ }
79
 
80
  /**
81
+ * @param string $id
82
+ * @param array $option
83
+ * @param array $data
84
+ *
85
+ * @return string
86
+ *
87
  * @internal
88
  */
89
+ protected function _render( $id, $option, $data ) {
90
+ $option['attr']['value'] = (string) $data['value'];
 
91
 
92
+ return '<input ' . fw_attr_to_html( $option['attr'] ) . ' type="text" />';
93
  }
94
 
95
  /**
96
+ * @param array $option
97
+ * @param array|null|string $input_value
98
+ *
99
+ * @return string
100
+ *
101
  * @internal
102
  */
103
+ protected function _get_value_from_input( $option, $input_value ) {
104
+ return (string) ( is_null( $input_value ) ? $option['value'] : $input_value );
 
105
  }
106
 
107
  /**
108
  * @internal
109
  */
110
+ protected function _get_defaults() {
 
111
  return array(
112
  'value' => ''
113
  );
114
  }
115
  }
 
116
 
117
+ FW_Option_Type::register( 'FW_Option_Type_Text' );
118
+
119
+ class FW_Option_Type_Short_Text extends FW_Option_Type_Text {
120
+ public function get_type() {
121
  return 'short-text';
122
  }
123
 
124
  /**
125
+ * @param string $id
126
+ * @param array $option
127
+ * @param array $data
128
+ *
129
+ * @return string
130
+ *
131
  * @internal
132
  */
133
+ protected function _render( $id, $option, $data ) {
 
134
  $option['attr']['class'] .= ' fw-option-width-short';
135
 
136
+ return parent::_render( $id, $option, $data );
137
  }
138
 
139
  /**
140
  * {@inheritdoc}
141
  * @internal
142
  */
143
+ public function _get_backend_width_type() {
 
144
  return 'auto';
145
  }
146
  }
 
147
 
148
+ FW_Option_Type::register( 'FW_Option_Type_Short_Text' );
149
+
150
+ class FW_Option_Type_Password extends FW_Option_Type {
151
+ public function get_type() {
152
  return 'password';
153
  }
154
 
156
  * @internal
157
  * {@inheritdoc}
158
  */
159
+ protected function _enqueue_static( $id, $option, $data ) {
160
+ }
161
 
162
  /**
163
+ * @param string $id
164
+ * @param array $option
165
+ * @param array $data
166
+ *
167
+ * @return string
168
+ *
169
  * @internal
170
  */
171
+ protected function _render( $id, $option, $data ) {
172
+ $option['attr']['value'] = (string) $data['value'];
 
173
 
174
+ return '<input ' . fw_attr_to_html( $option['attr'] ) . ' type="password" />';
175
  }
176
 
177
  /**
178
+ * @param array $option
179
+ * @param array|null|string $input_value
180
+ *
181
+ * @return string
182
+ *
183
  * @internal
184
  */
185
+ protected function _get_value_from_input( $option, $input_value ) {
186
+ return (string) ( is_null( $input_value ) ? $option['value'] : $input_value );
 
187
  }
188
 
189
  /**
190
  * @internal
191
  */
192
+ protected function _get_defaults() {
 
193
  return array(
194
  'value' => ''
195
  );
196
  }
197
  }
 
198
 
199
+ FW_Option_Type::register( 'FW_Option_Type_Password' );
200
+
201
+ class FW_Option_Type_Textarea extends FW_Option_Type {
202
+ public function get_type() {
203
  return 'textarea';
204
  }
205
 
207
  * @internal
208
  * {@inheritdoc}
209
  */
210
+ protected function _enqueue_static( $id, $option, $data ) {
211
+ }
212
 
213
  /**
214
+ * @param string $id
215
+ * @param array $option
216
+ * @param array $data
217
+ *
218
+ * @return string
219
+ *
220
  * @internal
221
  */
222
+ protected function _render( $id, $option, $data ) {
223
+ $option['value'] = (string) $data['value'];
 
224
 
225
+ unset( $option['attr']['value'] ); // be sure to remove value from attributes
226
 
227
+ $option['attr'] = array_merge( array( 'rows' => '6' ), $option['attr'] );
228
  $option['attr']['class'] .= ' code';
229
 
230
+ return '<textarea ' . fw_attr_to_html( $option['attr'] ) . '>' .
231
+ htmlspecialchars( $option['value'], ENT_COMPAT, 'UTF-8' ) .
232
+ '</textarea>';
233
  }
234
 
235
  /**
236
+ * @param array $option
237
+ * @param array|null|string $input_value
238
+ *
239
+ * @return string
240
+ *
241
  * @internal
242
  */
243
+ protected function _get_value_from_input( $option, $input_value ) {
244
+ return (string) ( is_null( $input_value ) ? $option['value'] : $input_value );
 
245
  }
246
 
247
  /**
248
  * @internal
249
  */
250
+ protected function _get_defaults() {
 
251
  return array(
252
  'value' => ''
253
  );
254
  }
255
  }
 
256
 
257
+ FW_Option_Type::register( 'FW_Option_Type_Textarea' );
258
+
259
+ class FW_Option_Type_Html extends FW_Option_Type {
260
+ public function get_type() {
261
  return 'html';
262
  }
263
 
265
  * @internal
266
  * {@inheritdoc}
267
  */
268
+ protected function _enqueue_static( $id, $option, $data ) {
269
+ }
270
 
271
  /**
272
+ * @param string $id
273
+ * @param array $option
274
+ * @param array $data
275
+ *
276
+ * @return string
277
+ *
278
  * @internal
279
  */
280
+ protected function _render( $id, $option, $data ) {
281
+ $option['attr']['value'] = (string) $data['value'];
 
282
 
283
  $div_attr = $option['attr'];
284
+ unset( $div_attr['name'] );
285
+ unset( $div_attr['value'] );
286
 
287
+ return '<div ' . fw_attr_to_html( $div_attr ) . '>' .
288
+ fw()->backend->option_type( 'hidden' )->render( $id, array(
289
+ 'attr' => array(
290
+ 'class' => 'fw-option-html-value',
291
+ ),
292
+ 'value' => $option['attr']['value'],
293
+ ),
294
+ array(
295
+ 'id_prefix' => $data['id_prefix'],
296
+ 'name_prefix' => $data['name_prefix']
297
+ )
298
+ ) .
299
+ '<div class="fw-option-html">' . $option['html'] . '</div>' .
300
+ '</div>';
301
  }
302
 
303
  /**
304
+ * @param array $option
305
+ * @param array|null|string $input_value
306
+ *
307
+ * @return string
308
+ *
309
  * @internal
310
  */
311
+ protected function _get_value_from_input( $option, $input_value ) {
312
+ return (string) ( is_null( $input_value ) ? $option['value'] : $input_value );
 
313
  }
314
 
315
  /**
316
  * @internal
317
  */
318
+ public function _get_backend_width_type() {
 
319
  return 'auto';
320
  }
321
 
322
  /**
323
  * @internal
324
  */
325
+ protected function _get_defaults() {
 
326
  return array(
327
  'value' => '',
328
  'html' => '<em>default html</em>',
329
  );
330
  }
331
  }
332
+
333
+ FW_Option_Type::register( 'FW_Option_Type_Html' );
334
 
335
  /**
336
  * Same html but displayed in fixed width
337
  */
338
+ class FW_Option_Type_Html_Fixed extends FW_Option_Type_Html {
339
+ public function get_type() {
 
 
340
  return 'html-fixed';
341
  }
342
 
343
  /**
344
  * @internal
345
  */
346
+ public function _get_backend_width_type() {
 
347
  return 'fixed';
348
  }
349
  }
350
+
351
+ FW_Option_Type::register( 'FW_Option_Type_Html_Fixed' );
352
 
353
  /**
354
  * Same html but displayed in full width
355
  */
356
+ class FW_Option_Type_Html_Full extends FW_Option_Type_Html {
357
+ public function get_type() {
 
 
358
  return 'html-full';
359
  }
360
 
361
  /**
362
  * @internal
363
  */
364
+ public function _get_backend_width_type() {
 
365
  return 'full';
366
  }
367
  }
 
368
 
369
+ FW_Option_Type::register( 'FW_Option_Type_Html_Full' );
370
+
371
+ class FW_Option_Type_Checkbox extends FW_Option_Type {
372
+ public function get_type() {
373
  return 'checkbox';
374
  }
375
 
377
  * @internal
378
  * {@inheritdoc}
379
  */
380
+ protected function _enqueue_static( $id, $option, $data ) {
381
+ }
382
 
383
  /**
384
+ * @param string $id
385
+ * @param array $option
386
+ * @param array $data
387
+ *
388
+ * @return string
389
+ *
390
  * @internal
391
  */
392
+ protected function _render( $id, $option, $data ) {
393
+ $option['value'] = (bool) $data['value'];
 
394
 
395
+ unset( $option['attr']['value'] );
396
 
397
+ return '<input type="checkbox" name="' . esc_attr( $option['attr']['name'] ) . '" value="" checked="checked" style="display: none">' .
398
+ '<!-- used for "' . esc_attr( $id ) . '" to be present in _POST -->' .
399
+ '' .
400
+ '<label for="' . esc_attr( $option['attr']['id'] ) . '">' .
401
+ '<input ' . fw_attr_to_html( $option['attr'] ) . ' type="checkbox" value="true" ' .
402
+ ( $option['value'] ? 'checked="checked" ' : '' ) .
403
+ '> ' . htmlspecialchars( $option['text'], ENT_COMPAT, 'UTF-8' ) .
404
+ '</label>';
405
  }
406
 
407
  /**
408
+ * @param array $option
409
+ * @param array|null|string $input_value
410
+ *
411
+ * @return bool
412
+ *
413
  * @internal
414
  */
415
+ protected function _get_value_from_input( $option, $input_value ) {
416
+ return (bool) ( is_null( $input_value ) ? $option['value'] : $input_value );
 
417
  }
418
 
419
  /**
420
  * @internal
421
  */
422
+ public function _get_backend_width_type() {
 
423
  return 'auto';
424
  }
425
 
426
  /**
427
  * @internal
428
  */
429
+ protected function _get_defaults() {
 
430
  return array(
431
  'value' => false,
432
+ 'text' => __( 'Yes', 'fw' ),
433
  );
434
  }
435
  }
436
+
437
+ FW_Option_Type::register( 'FW_Option_Type_Checkbox' );
438
 
439
  /**
440
  * Checkboxes list
441
  */
442
+ class FW_Option_Type_Checkboxes extends FW_Option_Type {
443
+ public function get_type() {
 
 
444
  return 'checkboxes';
445
  }
446
 
448
  * @internal
449
  * {@inheritdoc}
450
  */
451
+ protected function _enqueue_static( $id, $option, $data ) {
452
+ }
453
 
454
  /**
455
+ * @param string $id
456
+ * @param array $option
457
+ * @param array $data
458
+ *
459
+ * @return string
460
+ *
461
  * @internal
462
  */
463
+ protected function _render( $id, $option, $data ) {
464
+ $option['value'] = is_array( $data['value'] ) ? $data['value'] : array();
 
465
 
466
  $div_attr = $option['attr'];
467
+ unset( $div_attr['name'] );
468
+ unset( $div_attr['value'] );
469
 
470
+ if ( $option['inline'] ) {
471
  $div_attr['class'] .= ' fw-option-type-checkboxes-inline fw-clearfix';
472
  }
473
 
474
+ $html = '<div ' . fw_attr_to_html( $div_attr ) . '>';
475
 
476
+ $html .= '<input type="checkbox" name="' . esc_attr( $option['attr']['name'] ) . '[]" value="" checked="checked" style="display: none">' .
477
+ '<!-- used for "' . esc_attr( $id ) . '" to be present in _POST -->';
478
 
479
+ foreach ( $option['choices'] as $value => $text ) {
480
+ $choice_id = $option['attr']['id'] . '-' . $value;
481
 
482
+ $html .= '<div>' .
483
+ '<label for="' . esc_attr( $choice_id ) . '">' .
484
+ '<input type="checkbox" ' .
485
+ 'name="' . esc_attr( $option['attr']['name'] ) . '[' . esc_attr( $value ) . ']" ' .
486
+ 'value="true" ' .
487
+ 'id="' . esc_attr( $choice_id ) . '" ' .
488
+ ( isset( $option['value'][ $value ] ) && $option['value'][ $value ] ? 'checked="checked" ' : '' ) .
489
+ '> ' . htmlspecialchars( $text, ENT_COMPAT, 'UTF-8' ) .
490
+ '</label>' .
491
+ '</div>';
492
  }
493
 
494
  $html .= '</div>';
497
  }
498
 
499
  /**
500
+ * @param array $option
501
+ * @param array|null|string $input_value
502
+ *
503
+ * @return array
504
+ *
505
  * @internal
506
  */
507
+ protected function _get_value_from_input( $option, $input_value ) {
508
+ if ( is_array( $input_value ) ) {
 
509
  $value = array();
510
 
511
+ foreach ( $input_value as $choice => $val ) {
512
+ if ( $val === '' ) {
513
  continue;
514
+ }
515
 
516
+ if ( ! isset( $option['choices'][ $choice ] ) ) {
517
  continue;
518
+ }
519
 
520
+ $value[ $choice ] = true;
521
  }
522
  } else {
523
  $value = $option['value'];
529
  /**
530
  * @internal
531
  */
532
+ public function _get_backend_width_type() {
 
533
  return 'auto';
534
  }
535
 
536
  /**
537
  * @internal
538
  */
539
+ protected function _get_defaults() {
 
540
  return array(
541
  'inline' => false, // Set this parameter to true in case you want all checkbox inputs to be rendered inline
542
  'value' => array(),
544
  );
545
  }
546
  }
547
+
548
+ FW_Option_Type::register( 'FW_Option_Type_Checkboxes' );
549
 
550
  /**
551
  * Radio list
552
  */
553
+ class FW_Option_Type_Radio extends FW_Option_Type {
554
+ public function get_type() {
 
 
555
  return 'radio';
556
  }
557
 
559
  * @internal
560
  * {@inheritdoc}
561
  */
562
+ protected function _enqueue_static( $id, $option, $data ) {
563
+ }
564
 
565
  /**
566
+ * @param string $id
567
+ * @param array $option
568
+ * @param array $data
569
+ *
570
+ * @return string
571
+ *
572
  * @internal
573
  */
574
+ protected function _render( $id, $option, $data ) {
575
+ $option['value'] = (string) $data['value'];
 
576
 
577
  $div_attr = $option['attr'];
578
+ unset( $div_attr['name'] );
579
+ unset( $div_attr['value'] );
580
 
581
+ if ( $option['inline'] ) {
582
  $div_attr['class'] .= ' fw-option-type-radio-inline fw-clearfix';
583
  }
584
 
585
+ $html = '<div ' . fw_attr_to_html( $div_attr ) . '>';
586
+
587
+ foreach ( $option['choices'] as $value => $text ) {
588
+ $choice_id = $option['attr']['id'] . '-' . $value;
589
+
590
+ $html .= '<div>' .
591
+ '<label for="' . esc_attr( $choice_id ) . '">' .
592
+ '<input type="radio" ' .
593
+ 'name="' . esc_attr( $option['attr']['name'] ) . '" ' .
594
+ 'value="' . esc_attr( $value ) . '" ' .
595
+ 'id="' . esc_attr( $choice_id ) . '" ' .
596
+ ( $option['value'] == $value ? 'checked="checked" ' : '' ) .
597
+ '> ' . htmlspecialchars( $text, ENT_COMPAT, 'UTF-8' ) .
598
+ '</label>' .
599
+ '</div>';
600
  }
601
 
602
  $html .= '</div>';
605
  }
606
 
607
  /**
608
+ * @param array $option
609
+ * @param array|null|string $input_value
610
+ *
611
+ * @return string
612
+ *
613
  * @internal
614
  */
615
+ protected function _get_value_from_input( $option, $input_value ) {
616
+ if ( ! isset( $option['choices'][ $input_value ] ) ) {
 
617
  if (
618
+ empty( $option['choices'] ) ||
619
+ isset( $option['choices'][ $option['value'] ] )
620
  ) {
621
  $input_value = $option['value'];
622
  } else {
623
+ reset( $option['choices'] );
624
+ $input_value = key( $option['choices'] );
625
  }
626
  }
627
 
628
+ return (string) $input_value;
629
  }
630
 
631
  /**
632
  * @internal
633
  */
634
+ public function _get_backend_width_type() {
 
635
  return 'auto';
636
  }
637
 
638
  /**
639
  * @internal
640
  */
641
+ protected function _get_defaults() {
 
642
  return array(
643
+ 'inline' => false, // Set this parameter to true in case you want all radio inputs to be rendered inline
644
  'value' => '',
645
  'choices' => array()
646
  );
647
  }
648
  }
649
+
650
+ FW_Option_Type::register( 'FW_Option_Type_Radio' );
651
 
652
  /**
653
  * Select
654
  */
655
+ class FW_Option_Type_Select extends FW_Option_Type {
656
+ public function get_type() {
 
 
657
  return 'select';
658
  }
659
 
661
  * @internal
662
  * {@inheritdoc}
663
  */
664
+ protected function _enqueue_static( $id, $option, $data ) {
665
+ }
666
 
667
  /**
668
+ * @param string $id
669
+ * @param array $option
670
+ * @param array $data
671
+ *
672
+ * @return string
673
+ *
674
  * @internal
675
  */
676
+ protected function _render( $id, $option, $data ) {
 
677
  $option['value'] = $data['value'];
678
 
679
  $option['attr']['data-saved-value'] = $data['value'];
682
  $option['attr']['multiple']
683
  );
684
 
685
+ if ( ! isset( $option['choices'] ) ) {
686
  $option['choices'] = array();
687
  }
688
 
689
+ $html = '<select ' . fw_attr_to_html( $option['attr'] ) . '>' .
690
+ $this->render_choices( $option['choices'], $option['value'] ) .
691
+ '</select>';
692
 
693
  return $html;
694
  }
695
 
696
  /**
697
+ * @param array $option
698
+ * @param array|null|string $input_value
699
+ *
700
+ * @return string
701
+ *
702
  * @internal
703
  */
704
+ protected function _get_value_from_input( $option, $input_value ) {
705
+ if ( is_null( $input_value ) ) {
 
706
  return $option['value'];
707
  }
708
 
709
+ if ( empty( $option['no-validate'] ) ) {
710
+ $all_choices = $this->get_choices( $option['choices'] );
711
 
712
+ if ( ! isset( $all_choices[ $input_value ] ) ) {
713
  if (
714
+ empty( $all_choices ) ||
715
+ isset( $all_choices[ $option['value'] ] )
716
  ) {
717
  $input_value = $option['value'];
718
  } else {
719
+ reset( $all_choices );
720
+ $input_value = key( $all_choices );
721
  }
722
  }
723
 
724
+ unset( $all_choices );
725
  }
726
 
727
+ return (string) $input_value;
728
  }
729
 
730
  /**
731
  * Extract recursive from optgroups all choices as one level array
732
+ *
733
+ * @param array|null $choices
734
+ *
735
+ * @return array
736
+ *
737
+ * @internal
738
  */
739
+ protected function get_choices( $choices ) {
 
740
  $result = array();
741
 
742
+ foreach ( $choices as $cid => $choice ) {
743
+ if ( is_array( $choice ) && isset( $choice['choices'] ) ) {
744
  // optgroup
745
+ $result += $this->get_choices( $choice['choices'] );
746
  } else {
747
+ $result[ $cid ] = $choice;
748
  }
749
  }
750
 
751
  return $result;
752
  }
753
 
754
+ protected function render_choices( &$choices, &$value ) {
755
+ if ( empty( $choices ) || ! is_array( $choices ) ) {
 
756
  return '';
757
+ }
758
 
759
  $html = '';
760
 
761
+ foreach ( $choices as $c_value => $choice ) {
762
+ if ( is_array( $choice ) ) {
763
+ if ( ! isset( $choice['attr'] ) ) {
764
  $choice['attr'] = array();
765
  }
766
 
767
+ if ( isset( $choice['choices'] ) ) { // optgroup
768
+ $html .= '<optgroup ' . fw_attr_to_html( $choice['attr'] ) . '>' .
769
+ $this->render_choices( $choice['choices'], $value ) .
770
+ '</optgroup>';
771
  } else { // choice as array (with custom attributes)
772
  $choice['attr']['value'] = $c_value;
773
 
774
+ unset( $choice['attr']['selected'] ); // this is not allowed
775
 
776
+ $html .= '<option ' . fw_attr_to_html( $choice['attr'] ) . ' ' .
777
+ ( $c_value == $value ? 'selected="selected" ' : '' ) . '>' .
778
+ htmlspecialchars( isset( $choice['text'] ) ? $choice['text'] : '', ENT_COMPAT, 'UTF-8' ) .
779
+ '</option>';
780
  }
781
  } else { // simple choice
782
+ $html .= '<option value="' . esc_attr( $c_value ) . '" ' .
783
+ ( $c_value == $value ? 'selected="selected" ' : '' ) . '>' .
784
+ htmlspecialchars( $choice, ENT_COMPAT, 'UTF-8' ) .
785
+ '</option>';
786
  }
787
  }
788
 
792
  /**
793
  * @internal
794
  */
795
+ protected function _get_defaults() {
 
796
  return array(
797
  'value' => '',
798
  'choices' => array()
799
  );
800
  }
801
  }
 
802
 
803
+ FW_Option_Type::register( 'FW_Option_Type_Select' );
804
+
805
+ class FW_Option_Type_Short_Select extends FW_Option_Type_Select {
806
+ public function get_type() {
807
  return 'short-select';
808
  }
809
 
810
  /**
811
+ * @param string $id
812
+ * @param array $option
813
+ * @param array $data
814
+ *
815
+ * @return string
816
+ *
817
  * @internal
818
  */
819
+ protected function _render( $id, $option, $data ) {
 
820
  $option['attr']['class'] .= ' fw-option-width-short';
821
 
822
+ return parent::_render( $id, $option, $data );
823
  }
824
 
825
  /**
826
  * {@inheritdoc}
827
  * @internal
828
  */
829
+ public function _get_backend_width_type() {
 
830
  return 'auto';
831
  }
832
  }
833
+
834
+ FW_Option_Type::register( 'FW_Option_Type_Short_Select' );
835
 
836
  /**
837
  * Select Multiple
838
  */
839
+ class FW_Option_Type_Select_Multiple extends FW_Option_Type_Select {
840
+ public function get_type() {
 
 
841
  return 'select-multiple';
842
  }
843
 
845
  * @internal
846
  * {@inheritdoc}
847
  */
848
+ protected function _enqueue_static( $id, $option, $data ) {
849
+ }
850
 
851
  /**
852
+ * @param string $id
853
+ * @param array $option
854
+ * @param array $data
855
+ *
856
+ * @return string
857
+ *
858
  * @internal
859
  */
860
+ protected function _render( $id, $option, $data ) {
 
861
  $option['value'] = $data['value'];
862
 
863
+ unset( $option['attr']['value'] );
864
+
865
+ $html = '<input type="hidden" name="' . $option['attr']['name'] . '" value="">';
866
 
867
  $option['attr']['name'] .= '[]';
868
  $option['attr']['multiple'] = 'multiple';
869
 
870
+ if ( ! isset( $option['attr']['size'] ) ) {
871
  $option['attr']['size'] = '7';
872
  }
873
 
874
+ $html .= '<select ' . fw_attr_to_html( $option['attr'] ) . '>' .
875
+ $this->render_choices( $option['choices'], $option['value'] ) .
876
+ '</select>';
877
 
878
  return $html;
879
  }
880
 
881
  /**
882
+ * @param array $option
883
+ * @param array|null|string $input_value
884
+ *
885
+ * @return array|null|string
886
+ *
887
  * @internal
888
  */
889
+ protected function _get_value_from_input( $option, $input_value ) {
890
+ if ( is_null( $input_value ) ) {
 
891
  $input_value = $option['value'];
892
  }
893
 
894
+ if ( ! is_array( $input_value ) ) {
895
+ $input_value = array();
896
+ }
897
+
898
+ if ( empty( $option['no-validate'] ) ) {
899
+ $all_choices = $this->get_choices( $option['choices'] );
900
 
901
+ foreach ( $input_value as $key => $value ) {
902
+ if ( ! isset( $all_choices[ $value ] ) ) {
903
+ unset( $input_value[ $key ] );
904
  }
905
  }
906
 
907
+ unset( $all_choices );
908
  }
909
 
910
  return $input_value;
911
  }
912
 
913
+ protected function render_choices( &$choices, &$value ) {
914
+ if ( empty( $choices ) || ! is_array( $choices ) ) {
 
915
  return '';
916
+ }
917
 
918
  $html = '';
919
 
920
+ foreach ( $choices as $c_value => $choice ) {
921
+ if ( is_array( $choice ) ) {
922
+ if ( ! isset( $choice['attr'] ) ) {
923
  $choice['attr'] = array();
924
  }
925
 
926
+ if ( isset( $choice['choices'] ) ) { // optgroup
927
+ $html .= '<optgroup ' . fw_attr_to_html( $choice['attr'] ) . '>' .
928
+ $this->render_choices( $choice['choices'], $value ) .
929
+ '</optgroup>';
930
  } else { // choice as array (with custom attributes)
931
  $choice['attr']['value'] = $c_value;
932
 
933
+ unset( $choice['attr']['selected'] ); // this is not allowed
934
 
935
+ $html .= '<option ' . fw_attr_to_html( $choice['attr'] ) . ' ' .
936
+ ( in_array( $c_value, $value ) ? 'selected="selected" ' : '' ) . '>' .
937
+ htmlspecialchars( isset( $choice['text'] ) ? $choice['text'] : '', ENT_COMPAT, 'UTF-8' ) .
938
+ '</option>';
939
  }
940
  } else { // simple choice
941
+ $html .= '<option value="' . esc_attr( $c_value ) . '" ' .
942
+ ( in_array( $c_value, $value ) ? 'selected="selected" ' : '' ) . '>' .
943
+ htmlspecialchars( $choice, ENT_COMPAT, 'UTF-8' ) .
944
+ '</option>';
945
  }
946
  }
947
 
951
  /**
952
  * @internal
953
  */
954
+ protected function _get_defaults() {
 
955
  return array(
956
  'value' => array(),
957
  'choices' => array()
958
  );
959
  }
960
  }
961
+
962
+ FW_Option_Type::register( 'FW_Option_Type_Select_Multiple' );
framework/manifest.php CHANGED
@@ -4,4 +4,4 @@ $manifest = array();
4
 
5
  $manifest['name'] = __('Unyson', 'fw');
6
 
7
- $manifest['version'] = '2.3.0';
4
 
5
  $manifest['name'] = __('Unyson', 'fw');
6
 
7
+ $manifest['version'] = '2.3.1';
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: unyson, themefusecom
3
  Tags: page builder, cms, grid, layout, responsive, back up, backup, db backup, dump, migrate, schedule, search engine optimization, seo, media, slideshow, shortcode, slide, slideshare, slideshow, google sitemaps, sitemaps, analytics, google analytics, calendar, event, events, google maps, learning, lessons, sidebars, breadcrumbs, review, portfolio, framework
4
  Requires at least: 4.0.0
5
  Tested up to: 4.2
6
- Stable tag: 2.3.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -86,6 +86,10 @@ Yes; Unyson will work with any theme.
86
 
87
  == Changelog ==
88
 
 
 
 
 
89
  = 2.3.0 =
90
  * Options can be used in [Customizer](https://codex.wordpress.org/Theme_Customization_API) [#410](https://github.com/ThemeFuse/Unyson/issues/410)
91
  * Fixed [#77](https://github.com/ThemeFuse/Unyson/issues/77)
3
  Tags: page builder, cms, grid, layout, responsive, back up, backup, db backup, dump, migrate, schedule, search engine optimization, seo, media, slideshow, shortcode, slide, slideshare, slideshow, google sitemaps, sitemaps, analytics, google analytics, calendar, event, events, google maps, learning, lessons, sidebars, breadcrumbs, review, portfolio, framework
4
  Requires at least: 4.0.0
5
  Tested up to: 4.2
6
+ Stable tag: 2.3.1
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
86
 
87
  == Changelog ==
88
 
89
+ = 2.3.1 =
90
+ * Fixed [#566](https://github.com/ThemeFuse/Unyson/issues/566), [#550](https://github.com/ThemeFuse/Unyson/issues/550)
91
+ * Fixed: Options default values not working in Customizer [#410](https://github.com/ThemeFuse/Unyson/issues/410#issuecomment-103343955)
92
+
93
  = 2.3.0 =
94
  * Options can be used in [Customizer](https://codex.wordpress.org/Theme_Customization_API) [#410](https://github.com/ThemeFuse/Unyson/issues/410)
95
  * Fixed [#77](https://github.com/ThemeFuse/Unyson/issues/77)
unyson.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Unyson
4
  * Plugin URI: http://unyson.themefuse.com/
5
  * Description: A free drag & drop framework that comes with a bunch of built in extensions that will help you develop premium themes fast & easy.
6
- * Version: 2.3.0
7
  * Author: ThemeFuse
8
  * Author URI: http://themefuse.com
9
  * License: GPL2+
3
  * Plugin Name: Unyson
4
  * Plugin URI: http://unyson.themefuse.com/
5
  * Description: A free drag & drop framework that comes with a bunch of built in extensions that will help you develop premium themes fast & easy.
6
+ * Version: 2.3.1
7
  * Author: ThemeFuse
8
  * Author URI: http://themefuse.com
9
  * License: GPL2+