Unyson - Version 2.6.11

Version Description

  • Fixed #2198, #2216, #2219, #2234, #2254, #2264, #2265, #2273
  • Option-type multi-select improvements
  • Option-type multi-picker: The same options can be used for multiple choices #2251
  • Autoload a lot of classes #2225
  • New helper function fw_get_path_url()
  • Deprecated warning for the save-in-separate-meta option parameter
  • Deleted FW_File_Cache helper
Download this release

Release Info

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

Code changes from version 2.6.10 to 2.6.11

Files changed (69) hide show
  1. framework/autoload.php +301 -0
  2. framework/bootstrap.php +7 -43
  3. framework/core/Fw.php +0 -10
  4. framework/core/components/backend.php +270 -136
  5. framework/core/components/extensions.php +3 -19
  6. framework/core/components/extensions/manager/class--fw-extensions-manager.php +1 -19
  7. framework/core/components/extensions/manager/includes/class--fw-extensions-delete-upgrader-skin.php +1 -1
  8. framework/core/components/extensions/manager/includes/class--fw-extensions-install-upgrader-skin.php +1 -1
  9. framework/core/components/extensions/manager/includes/download-source/types/init.php +0 -3
  10. framework/core/components/theme.php +6 -14
  11. framework/core/exceptions/class-fw-option-type-exception.php +40 -0
  12. framework/core/extends/class-fw-extension.php +12 -31
  13. framework/core/extends/class-fw-option-type.php +16 -13
  14. framework/extensions/update/includes/classes/class--fw-ext-update-extensions-upgrader-skin.php +1 -1
  15. framework/extensions/update/includes/classes/class--fw-ext-update-framework-upgrader-skin.php +1 -1
  16. framework/extensions/update/includes/classes/class--fw-ext-update-theme-upgrader-skin.php +1 -1
  17. framework/extensions/update/manifest.php +1 -1
  18. framework/helpers/class-fw-flash-messages.php +4 -0
  19. framework/helpers/fw-storage.php +15 -13
  20. framework/helpers/general.php +204 -44
  21. framework/includes/container-types/box/class-fw-container-type-box.php +0 -1
  22. framework/includes/container-types/popup/class-fw-container-type-popup.php +0 -1
  23. framework/includes/container-types/simple.php +0 -1
  24. framework/includes/container-types/tab/class-fw-container-type-tab.php +0 -1
  25. framework/includes/customizer/class--fw-customizer-control-option-wrapper.php +1 -3
  26. framework/includes/customizer/class--fw-customizer-setting-option.php +32 -0
  27. framework/includes/hooks.php +138 -52
  28. framework/includes/option-storage/type/class-fw-option-storage-type-term-meta.php +87 -0
  29. framework/includes/option-types/addable-box/class-fw-option-type-addable-box.php +0 -1
  30. framework/includes/option-types/addable-option/class-fw-option-type-addable-option.php +0 -1
  31. framework/includes/option-types/addable-popup/class-fw-option-type-addable-popup.php +1 -5
  32. framework/includes/option-types/background-image/class-fw-option-type-background-image.php +0 -2
  33. framework/includes/option-types/color-picker/class-fw-option-type-color-picker.php +0 -1
  34. framework/includes/option-types/date-picker/class-fw-option-type-wp-date-picker.php +1 -3
  35. framework/includes/option-types/datetime-picker/class-fw-option-type-datetime-picker.php +1 -2
  36. framework/includes/option-types/datetime-range/class-fw-option-type-datetime-range.php +1 -2
  37. framework/includes/option-types/gradient/class-fw-option-type-gradient.php +1 -3
  38. framework/includes/option-types/icon-v2/class-fw-option-type-icon-v2.php +0 -8
  39. framework/includes/option-types/icon-v2/includes/class-fw-icon-v2-packs-loader.php +1 -1
  40. framework/includes/option-types/icon/class-fw-option-type-icon.php +1 -2
  41. framework/includes/option-types/image-picker/class-fw-option-type-image-picker.php +1 -3
  42. framework/includes/option-types/map/class-fw-option-type-map.php +1 -3
  43. framework/includes/option-types/multi-picker/class-fw-option-type-multi-picker.php +55 -1
  44. framework/includes/option-types/multi-select/class-fw-option-type-multi-select.php +190 -318
  45. framework/includes/option-types/multi-select/static/css/style.css +0 -15
  46. framework/includes/option-types/multi-select/static/js/scripts.js +75 -52
  47. framework/includes/option-types/multi-upload/class-fw-option-type-multi-upload.php +1 -2
  48. framework/includes/option-types/multi/class-fw-option-type-multi.php +1 -2
  49. framework/includes/option-types/oembed/class-fw-option-type-oembed.php +1 -3
  50. framework/includes/option-types/popup/class-fw-option-type-popup.php +1 -3
  51. framework/includes/option-types/radio-text/class-fw-option-type-radio-text.php +1 -2
  52. framework/includes/option-types/range-slider/class-fw-option-type-range-slider.php +1 -3
  53. framework/includes/option-types/rgba-color-picker/class-fw-option-type-rgba-color-picker.php +1 -3
  54. framework/includes/option-types/simple.php +1 -32
  55. framework/includes/option-types/slider/class-fw-option-type-short-slider.php +1 -3
  56. framework/includes/option-types/slider/class-fw-option-type-slider.php +1 -3
  57. framework/includes/option-types/switch/class-fw-option-type-switch.php +1 -2
  58. framework/includes/option-types/typography-v2/class-fw-option-type-typography-v2.php +1 -3
  59. framework/includes/option-types/typography/class-fw-option-type-typography.php +1 -3
  60. framework/includes/option-types/upload/class-fw-option-type-upload.php +1 -2
  61. framework/includes/option-types/wp-editor/class-fw-option-type-wp-editor.php +1 -3
  62. framework/includes/option-types/wp-editor/static/scripts.js +4 -1
  63. framework/manifest.php +1 -1
  64. framework/static/css/backend-options.css +47 -19
  65. framework/static/css/fw.css +30 -12
  66. framework/static/js/fw.js +121 -24
  67. framework/views/backend-settings-form.php +20 -11
  68. readme.txt +13 -159
  69. unyson.php +2 -11
framework/autoload.php ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'FW' ) ) {
2
+ die( 'Forbidden' );
3
+ }
4
+
5
+ spl_autoload_register( '_fw_core_autoload' );
6
+ function _fw_core_autoload( $class ) {
7
+ switch ( $class ) {
8
+ case 'FW_Manifest' :
9
+ case 'FW_Framework_Manifest' :
10
+ case 'FW_Theme_Manifest' :
11
+ case 'FW_Extension_Manifest' :
12
+ require_once dirname( __FILE__ ) . '/core/class-fw-manifest.php';
13
+ break;
14
+ }
15
+ }
16
+
17
+ spl_autoload_register( '_fw_core_components_autoload' );
18
+ function _fw_core_components_autoload( $class ) {
19
+ switch ( $class ) {
20
+ case '_FW_Component_Backend' :
21
+ require_once dirname( __FILE__ ) . '/core/components/backend.php';
22
+ break;
23
+ case '_FW_Component_Extensions' :
24
+ require_once dirname( __FILE__ ) . '/core/components/extensions.php';
25
+ break;
26
+ case '_FW_Component_Theme' :
27
+ require_once dirname( __FILE__ ) . '/core/components/theme.php';
28
+ break;
29
+ case 'FW_Settings_Form_Theme' :
30
+ require_once dirname( __FILE__ ) . '/core/components/backend/class-fw-settings-form-theme.php';
31
+ break;
32
+ }
33
+ }
34
+
35
+ spl_autoload_register( '_fw_core_components_extensions_autoload' );
36
+ function _fw_core_components_extensions_autoload( $class ) {
37
+ switch ( $class ) {
38
+ case 'FW_Extension_Default' :
39
+ require_once dirname( __FILE__ ) . '/core/components/extensions/class-fw-extension-default.php';
40
+ break;
41
+ case '_FW_Extensions_Manager' :
42
+ require_once dirname( __FILE__ ) . '/core/components/extensions/manager/class--fw-extensions-manager.php';
43
+ break;
44
+ case '_FW_Extensions_Delete_Upgrader_Skin' :
45
+ require_once dirname( __FILE__ ) . '/core/components/extensions/manager/includes/class--fw-extensions-delete-upgrader-skin.php';
46
+ break;
47
+ case '_FW_Extensions_Install_Upgrader_Skin' :
48
+ require_once dirname( __FILE__ ) . '/core/components/extensions/manager/includes/class--fw-extensions-install-upgrader-skin.php';
49
+ break;
50
+ case 'Parsedown' :
51
+ require_once dirname( __FILE__ ) . '/core/components/extensions/manager/includes/parsedown/Parsedown.php';
52
+ break;
53
+ case 'FW_Ext_Download_Source' :
54
+ require_once dirname( __FILE__ ) . '/core/components/extensions/manager/includes/download-source/class--fw-ext-download-source.php';
55
+ break;
56
+ case '_FW_Ext_Download_Source_Register' :
57
+ require_once dirname( __FILE__ ) . '/core/components/extensions/manager/includes/download-source/class--fw-ext-download-source-register.php';
58
+ break;
59
+ case 'FW_Ext_Download_Source_Github' :
60
+ require_once dirname( __FILE__ ) . '/core/components/extensions/manager/includes/download-source/types/class-fw-download-source-github.php';
61
+ break;
62
+ case '_FW_Available_Extensions_Register' :
63
+ require_once dirname( __FILE__ ) . '/core/components/extensions/manager/includes/available-ext/class--fw-available-extensions-register.php';
64
+ break;
65
+ case 'FW_Available_Extension' :
66
+ require_once dirname( __FILE__ ) . '/core/components/extensions/manager/includes/available-ext/class-fw-available-extension.php';
67
+ break;
68
+ }
69
+ }
70
+
71
+ spl_autoload_register( '_fw_core_extends_autoload' );
72
+ function _fw_core_extends_autoload( $class ) {
73
+ switch ( $class ) {
74
+ case 'FW_Container_Type' :
75
+ require_once dirname( __FILE__ ) . '/core/extends/class-fw-container-type.php';
76
+ break;
77
+ case 'FW_Option_Type' :
78
+ require_once dirname( __FILE__ ) . '/core/extends/class-fw-option-type.php';
79
+ break;
80
+ case 'FW_Extension' :
81
+ require_once dirname( __FILE__ ) . '/core/extends/class-fw-extension.php';
82
+ break;
83
+ case 'FW_Option_Handler' :
84
+ require_once dirname( __FILE__ ) . '/core/extends/interface-fw-option-handler.php';
85
+ break;
86
+ }
87
+ }
88
+
89
+ spl_autoload_register( '_fw_code_exceptions_autoload' );
90
+ function _fw_code_exceptions_autoload( $class ) {
91
+ switch ( $class ) {
92
+ case 'FW_Option_Type_Exception' :
93
+ case 'FW_Option_Type_Exception_Not_Found' :
94
+ case 'FW_Option_Type_Exception_Invalid_Class' :
95
+ case 'FW_Option_Type_Exception_Already_Registered' :
96
+ require_once dirname( __FILE__ ) . '/core/exceptions/class-fw-option-type-exception.php';
97
+ break;
98
+ }
99
+ }
100
+
101
+ // Autoload helper classes
102
+ function _fw_autoload_helper_classes($class) {
103
+ static $class_to_file = array(
104
+ 'FW_Dumper' => 'class-fw-dumper',
105
+ 'FW_Cache' => 'class-fw-cache',
106
+ 'FW_Access_Key' => 'class-fw-access-key',
107
+ 'FW_WP_Filesystem' => 'class-fw-wp-filesystem',
108
+ 'FW_Form' => 'class-fw-form',
109
+ 'FW_Settings_Form' => 'class-fw-settings-form',
110
+ 'FW_Request' => 'class-fw-request',
111
+ 'FW_Session' => 'class-fw-session',
112
+ 'FW_WP_Option' => 'class-fw-wp-option',
113
+ 'FW_WP_Meta' => 'class-fw-wp-meta',
114
+ 'FW_Db_Options_Model' => 'class-fw-db-options-model',
115
+ 'FW_Flash_Messages' => 'class-fw-flash-messages',
116
+ 'FW_Resize' => 'class-fw-resize',
117
+ 'FW_WP_List_Table' => 'class-fw-wp-list-table',
118
+ 'FW_Type' => 'type/class-fw-type',
119
+ 'FW_Type_Register' => 'type/class-fw-type-register',
120
+ );
121
+
122
+ if (isset($class_to_file[$class])) {
123
+ require dirname(__FILE__) .'/helpers/'. $class_to_file[$class] .'.php';
124
+ }
125
+ }
126
+ spl_autoload_register('_fw_autoload_helper_classes');
127
+
128
+ spl_autoload_register( '_fw_includes_container_types_autoload' );
129
+ function _fw_includes_container_types_autoload( $class ) {
130
+ switch ( $class ) {
131
+ case 'FW_Container_Type_Undefined' :
132
+ require_once dirname( __FILE__ ) . '/includes/container-types/class-fw-container-type-undefined.php';
133
+ break;
134
+ case 'FW_Container_Type_Group' :
135
+ require_once dirname( __FILE__ ) . '/includes/container-types/simple.php';
136
+ break;
137
+ case 'FW_Container_Type_Box' :
138
+ require_once dirname( __FILE__ ) . '/includes/container-types/box/class-fw-container-type-box.php';
139
+ break;
140
+ case 'FW_Container_Type_Popup' :
141
+ require_once dirname( __FILE__ ) . '/includes/container-types/popup/class-fw-container-type-popup.php';
142
+ break;
143
+ case 'FW_Container_Type_Tab' :
144
+ require_once dirname( __FILE__ ) . '/includes/container-types/tab/class-fw-container-type-tab.php';
145
+ break;
146
+ }
147
+ }
148
+
149
+ spl_autoload_register( '_fw_includes_customizer_autoload' );
150
+ function _fw_includes_customizer_autoload( $class ) {
151
+ switch ( $class ) {
152
+ case '_FW_Customizer_Control_Option_Wrapper' :
153
+ require_once dirname( __FILE__ ) . '/includes/customizer/class--fw-customizer-control-option-wrapper.php';
154
+ break;
155
+ case '_FW_Customizer_Setting_Option' :
156
+ require_once dirname( __FILE__ ) . '/includes/customizer/class--fw-customizer-setting-option.php';
157
+ break;
158
+ }
159
+ }
160
+
161
+ spl_autoload_register( '_fw_includes_option_storage_autoload' );
162
+ function _fw_includes_option_storage_autoload( $class ) {
163
+ switch ( $class ) {
164
+ case '_FW_Option_Storage_Type_Register' :
165
+ require_once dirname( __FILE__ ) . '/includes/option-storage/class--fw-option-storage-type-register.php';
166
+ break;
167
+ case 'FW_Option_Storage_Type' :
168
+ require_once dirname( __FILE__ ) . '/includes/option-storage/class-fw-option-storage-type.php';
169
+ break;
170
+ case 'FW_Option_Storage_Type_Post_Meta' :
171
+ require_once dirname( __FILE__ ) . '/includes/option-storage/type/class-fw-option-storage-type-post-meta.php';
172
+ break;
173
+ case 'FW_Option_Storage_Type_Term_Meta' :
174
+ require_once dirname( __FILE__ ) . '/includes/option-storage/type/class-fw-option-storage-type-term-meta.php';
175
+ break;
176
+ case 'FW_Option_Storage_Type_WP_Option' :
177
+ require_once dirname( __FILE__ ) . '/includes/option-storage/type/class-fw-option-storage-type-wp-option.php';
178
+ break;
179
+ }
180
+ }
181
+
182
+ spl_autoload_register( '_fw_includes_option_types_autoload' );
183
+ function _fw_includes_option_types_autoload( $class ) {
184
+ switch ( $class ) {
185
+ case 'FW_Option_Type_Undefined' :
186
+ require_once dirname( __FILE__ ) . '/includes/option-types/class-fw-option-type-undefined.php';
187
+ break;
188
+ case 'FW_Option_Type_Hidden' :
189
+ case 'FW_Option_Type_Text' :
190
+ case 'FW_Option_Type_Short_Text' :
191
+ case 'FW_Option_Type_Password' :
192
+ case 'FW_Option_Type_Textarea' :
193
+ case 'FW_Option_Type_Html' :
194
+ case 'FW_Option_Type_Html_Fixed' :
195
+ case 'FW_Option_Type_Html_Full' :
196
+ case 'FW_Option_Type_Checkbox' :
197
+ case 'FW_Option_Type_Checkboxes' :
198
+ case 'FW_Option_Type_Radio' :
199
+ case 'FW_Option_Type_Select' :
200
+ case 'FW_Option_Type_Short_Select' :
201
+ case 'FW_Option_Type_Select_Multiple' :
202
+ case 'FW_Option_Type_Unique' :
203
+ case 'FW_Option_Type_GMap_Key' :
204
+ require_once dirname( __FILE__ ) . '/includes/option-types/simple.php';
205
+ break;
206
+ case 'FW_Option_Type_Addable_Box' :
207
+ require_once dirname( __FILE__ ) . '/includes/option-types/addable-box/class-fw-option-type-addable-box.php';
208
+ break;
209
+ case 'FW_Option_Type_Addable_Popup' :
210
+ case 'FW_Option_Type_Addable_Popup_Full' :
211
+ require_once dirname( __FILE__ ) . '/includes/option-types/addable-popup/class-fw-option-type-addable-popup.php';
212
+ break;
213
+ case 'FW_Option_Type_Addable_Option' :
214
+ require_once dirname( __FILE__ ) . '/includes/option-types/addable-option/class-fw-option-type-addable-option.php';
215
+ break;
216
+ case 'FW_Option_Type_Background_Image' :
217
+ require_once dirname( __FILE__ ) . '/includes/option-types/background-image/class-fw-option-type-background-image.php';
218
+ break;
219
+ case 'FW_Option_Type_Color_Picker' :
220
+ require_once dirname( __FILE__ ) . '/includes/option-types/color-picker/class-fw-option-type-color-picker.php';
221
+ break;
222
+ case 'FW_Option_Type_Date_Picker' :
223
+ require_once dirname( __FILE__ ) . '/includes/option-types/date-picker/class-fw-option-type-wp-date-picker.php';
224
+ break;
225
+ case 'FW_Option_Type_Datetime_Picker' :
226
+ require_once dirname( __FILE__ ) . '/includes/option-types/datetime-picker/class-fw-option-type-datetime-picker.php';
227
+ break;
228
+ case 'FW_Option_Type_Datetime_Range' :
229
+ require_once dirname( __FILE__ ) . '/includes/option-types/datetime-range/class-fw-option-type-datetime-range.php';
230
+ break;
231
+ case 'FW_Option_Type_Gradient' :
232
+ require_once dirname( __FILE__ ) . '/includes/option-types/gradient/class-fw-option-type-gradient.php';
233
+ break;
234
+ case 'FW_Option_Type_Icon' :
235
+ require_once dirname( __FILE__ ) . '/includes/option-types/icon/class-fw-option-type-icon.php';
236
+ break;
237
+ case 'FW_Option_Type_Icon_v2' :
238
+ require_once dirname( __FILE__ ) . '/includes/option-types/icon-v2/class-fw-option-type-icon-v2.php';
239
+ break;
240
+ case 'FW_Option_Type_Image_Picker' :
241
+ require_once dirname( __FILE__ ) . '/includes/option-types/image-picker/class-fw-option-type-image-picker.php';
242
+ break;
243
+ case 'FW_Option_Type_Map' :
244
+ require_once dirname( __FILE__ ) . '/includes/option-types/map/class-fw-option-type-map.php';
245
+ break;
246
+ case 'FW_Option_Type_Multi' :
247
+ require_once dirname( __FILE__ ) . '/includes/option-types/multi/class-fw-option-type-multi.php';
248
+ break;
249
+ case 'FW_Option_Type_Multi_Picker' :
250
+ require_once dirname( __FILE__ ) . '/includes/option-types/multi-picker/class-fw-option-type-multi-picker.php';
251
+ break;
252
+ case 'FW_Option_Type_Multi_Select' :
253
+ require_once dirname( __FILE__ ) . '/includes/option-types/multi-select/class-fw-option-type-multi-select.php';
254
+ break;
255
+ case 'FW_Option_Type_Multi_Upload' :
256
+ require_once dirname( __FILE__ ) . '/includes/option-types/multi-upload/class-fw-option-type-multi-upload.php';
257
+ break;
258
+ case 'FW_Option_Type_Oembed' :
259
+ require_once dirname( __FILE__ ) . '/includes/option-types/oembed/class-fw-option-type-oembed.php';
260
+ break;
261
+ case 'FW_Option_Type_Popup' :
262
+ require_once dirname( __FILE__ ) . '/includes/option-types/popup/class-fw-option-type-popup.php';
263
+ break;
264
+ case 'FW_Option_Type_Radio_Text' :
265
+ require_once dirname( __FILE__ ) . '/includes/option-types/radio-text/class-fw-option-type-radio-text.php';
266
+ break;
267
+ case 'FW_Option_Type_Range_Slider' :
268
+ require_once dirname( __FILE__ ) . '/includes/option-types/range-slider/class-fw-option-type-range-slider.php';
269
+ break;
270
+ case 'FW_Option_Type_Rgba_Color_Picker' :
271
+ require_once dirname( __FILE__ ) . '/includes/option-types/rgba-color-picker/class-fw-option-type-rgba-color-picker.php';
272
+ break;
273
+ case 'FW_Option_Type_Slider' :
274
+ require_once dirname( __FILE__ ) . '/includes/option-types/slider/class-fw-option-type-slider.php';
275
+ break;
276
+ case 'FW_Option_Type_Slider_Short' :
277
+ require_once dirname( __FILE__ ) . '/includes/option-types/slider/class-fw-option-type-short-slider.php';
278
+ break;
279
+ case 'FW_Option_Type_Switch' :
280
+ require_once dirname( __FILE__ ) . '/includes/option-types/switch/class-fw-option-type-switch.php';
281
+ break;
282
+ case 'FW_Option_Type_Typography' :
283
+ require_once dirname( __FILE__ ) . '/includes/option-types/typography/class-fw-option-type-typography.php';
284
+ break;
285
+ case 'FW_Option_Type_Typography_v2' :
286
+ require_once dirname( __FILE__ ) . '/includes/option-types/typography-v2/class-fw-option-type-typography-v2.php';
287
+ break;
288
+ case 'FW_Option_Type_Upload' :
289
+ require_once dirname( __FILE__ ) . '/includes/option-types/upload/class-fw-option-type-upload.php';
290
+ break;
291
+ case 'FW_Option_Type_Wp_Editor' :
292
+ require_once dirname( __FILE__ ) . '/includes/option-types/wp-editor/class-fw-option-type-wp-editor.php';
293
+ break;
294
+ case 'FW_Icon_V2_Favorites_Manager' :
295
+ require_once dirname( __FILE__ ) . '/includes/option-types/icon-v2/includes/class-fw-icon-v2-favorites.php';
296
+ break;
297
+ case 'FW_Icon_V2_Packs_Loader' :
298
+ require_once dirname( __FILE__ ) . '/includes/option-types/icon-v2/includes/class-fw-icon-v2-packs-loader.php';
299
+ break;
300
+ }
301
+ }
framework/bootstrap.php CHANGED
@@ -20,59 +20,23 @@ if (defined('FW')) {
20
 
21
  do_action('fw_before_init');
22
 
23
- $fw_dir = dirname(__FILE__);
24
 
25
- include $fw_dir .'/bootstrap-helpers.php';
26
 
27
- // these are required when fw() is executed below
28
- {
29
- require $fw_dir .'/helpers/class-fw-dumper.php';
30
- require $fw_dir .'/helpers/general.php';
31
- require $fw_dir .'/helpers/class-fw-cache.php';
32
  }
33
 
34
  // Load core
35
  {
36
- require $fw_dir .'/core/Fw.php';
37
 
38
  fw();
39
  }
40
 
41
- // Helpers
42
- {
43
- // Autoload helper classes
44
- function _fw_autoload_helper_classes($class) {
45
- static $class_to_file = array(
46
- 'FW_Access_Key' => 'class-fw-access-key',
47
- 'FW_WP_Filesystem' => 'class-fw-wp-filesystem',
48
- 'FW_File_Cache' => 'class-fw-file-cache',
49
- 'FW_Form' => 'class-fw-form',
50
- 'FW_Settings_Form' => 'class-fw-settings-form',
51
- 'FW_Request' => 'class-fw-request',
52
- 'FW_Session' => 'class-fw-session',
53
- 'FW_WP_Option' => 'class-fw-wp-option',
54
- 'FW_WP_Meta' => 'class-fw-wp-meta',
55
- 'FW_Db_Options_Model' => 'class-fw-db-options-model',
56
- 'FW_Flash_Messages' => 'class-fw-flash-messages',
57
- 'FW_Resize' => 'class-fw-resize',
58
- 'FW_WP_List_Table' => 'class-fw-wp-list-table',
59
- 'FW_Type' => 'type/class-fw-type',
60
- 'FW_Type_Register' => 'type/class-fw-type-register',
61
- );
62
-
63
- if (isset($class_to_file[$class])) {
64
- require dirname(__FILE__) .'/helpers/'. $class_to_file[$class] .'.php';
65
- }
66
- }
67
- spl_autoload_register('_fw_autoload_helper_classes');
68
-
69
- // Load helper functions
70
- foreach (array('meta', 'fw-storage', 'database') as $file) {
71
- require $fw_dir .'/helpers/'. $file .'.php';
72
- }
73
- }
74
-
75
- require $fw_dir .'/includes/hooks.php';
76
 
77
  /**
78
  * Init components
20
 
21
  do_action('fw_before_init');
22
 
23
+ $dir = dirname(__FILE__);
24
 
25
+ require $dir .'/autoload.php';
26
 
27
+ // Load helper functions
28
+ foreach (array('general', 'meta', 'fw-storage', 'database') as $file) {
29
+ require $dir .'/helpers/'. $file .'.php';
 
 
30
  }
31
 
32
  // Load core
33
  {
34
+ require $dir .'/core/Fw.php';
35
 
36
  fw();
37
  }
38
 
39
+ require $dir .'/includes/hooks.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
  /**
42
  * Init components
framework/core/Fw.php CHANGED
@@ -34,8 +34,6 @@ final class _Fw
34
 
35
  // manifest
36
  {
37
- require $fw_dir .'/core/class-fw-manifest.php';
38
-
39
  require $fw_dir .'/manifest.php';
40
  /** @var array $manifest */
41
 
@@ -44,18 +42,10 @@ final class _Fw
44
  add_action('fw_init', array($this, '_check_requirements'), 1);
45
  }
46
 
47
- require $fw_dir .'/core/extends/class-fw-extension.php';
48
- require $fw_dir .'/core/extends/interface-fw-option-handler.php'; // option handler (experimental)
49
-
50
  // components
51
  {
52
- require $fw_dir .'/core/components/extensions.php';
53
  $this->extensions = new _FW_Component_Extensions();
54
-
55
- require $fw_dir .'/core/components/backend.php';
56
  $this->backend = new _FW_Component_Backend();
57
-
58
- require $fw_dir .'/core/components/theme.php';
59
  $this->theme = new _FW_Component_Theme();
60
  }
61
  }
34
 
35
  // manifest
36
  {
 
 
37
  require $fw_dir .'/manifest.php';
38
  /** @var array $manifest */
39
 
42
  add_action('fw_init', array($this, '_check_requirements'), 1);
43
  }
44
 
 
 
 
45
  // components
46
  {
 
47
  $this->extensions = new _FW_Component_Extensions();
 
 
48
  $this->backend = new _FW_Component_Backend();
 
 
49
  $this->theme = new _FW_Component_Theme();
50
  }
51
  }
framework/core/components/backend.php CHANGED
@@ -25,14 +25,6 @@ final class _FW_Component_Backend {
25
  */
26
  private $markdown_parser = null;
27
 
28
- /**
29
- * Store option types for registration, until they will be required
30
- * @var array|false
31
- * array Can have some pending option types in it
32
- * false Option types already requested and was registered, so do not use pending anymore
33
- */
34
- private $option_types_pending_registration = array();
35
-
36
  /**
37
  * Contains all option types
38
  * @var FW_Option_Type[]
@@ -70,6 +62,8 @@ final class _FW_Component_Backend {
70
  */
71
  private $access_key;
72
 
 
 
73
  /**
74
  * @internal
75
  */
@@ -151,7 +145,6 @@ final class _FW_Component_Backend {
151
  */
152
  public function _init() {
153
  if ( is_admin() ) {
154
- require_once dirname(__FILE__) .'/backend/class-fw-settings-form-theme.php';
155
  $this->settings_form = new FW_Settings_Form_Theme('theme-settings');
156
  }
157
 
@@ -217,74 +210,62 @@ final class _FW_Component_Backend {
217
 
218
  /**
219
  * @param string|FW_Option_Type $option_type_class
 
220
  *
221
  * @internal
222
  */
223
- private function register_option_type( $option_type_class ) {
224
- if ( is_array( $this->option_types_pending_registration ) ) {
225
- // Option types never requested. Continue adding to pending
226
- $this->option_types_pending_registration[] = $option_type_class;
227
- } else {
228
- if ( is_string( $option_type_class ) ) {
229
- $option_type_class = new $option_type_class;
230
- }
231
-
232
- if ( ! is_subclass_of( $option_type_class, 'FW_Option_Type' ) ) {
233
- trigger_error( 'Invalid option type class ' . get_class( $option_type_class ), E_USER_WARNING );
234
- return;
235
  }
 
236
 
237
- /**
238
- * @var FW_Option_Type $option_type_class
239
- */
240
-
241
- $type = $option_type_class->get_type();
242
-
243
  if ( isset( $this->option_types[ $type ] ) ) {
244
  trigger_error( 'Option type "' . $type . '" already registered', E_USER_WARNING );
 
245
  return;
246
  }
247
-
248
- $this->option_types[ $type ] = $option_type_class;
249
-
250
- $this->option_types[ $type ]->_call_init($this->get_access_key());
251
  }
 
 
252
  }
253
 
254
  /**
255
  * @param string|FW_Container_Type $container_type_class
 
256
  *
257
  * @internal
258
  */
259
- private function register_container_type( $container_type_class ) {
260
- if ( is_array( $this->container_types_pending_registration ) ) {
261
- // Container types never requested. Continue adding to pending
262
- $this->container_types_pending_registration[] = $container_type_class;
263
- } else {
264
- if ( is_string( $container_type_class ) ) {
265
- $container_type_class = new $container_type_class;
266
- }
267
-
268
- if ( ! is_subclass_of( $container_type_class, 'FW_Container_Type' ) ) {
269
- trigger_error( 'Invalid container type class ' . get_class( $container_type_class ), E_USER_WARNING );
270
- return;
271
  }
 
272
 
273
- /**
274
- * @var FW_Container_Type $container_type_class
275
- */
276
-
277
- $type = $container_type_class->get_type();
278
-
279
  if ( isset( $this->container_types[ $type ] ) ) {
280
  trigger_error( 'Container type "' . $type . '" already registered', E_USER_WARNING );
 
281
  return;
282
  }
283
-
284
- $this->container_types[ $type ] = $container_type_class;
285
-
286
- $this->container_types[ $type ]->_call_init($this->get_access_key());
287
  }
 
 
288
  }
289
 
290
  private function register_static() {
@@ -447,11 +428,18 @@ final class _FW_Component_Backend {
447
  }
448
 
449
  wp_register_style(
450
- 'fw-font-awesome',
451
  fw_get_framework_directory_uri( '/static/libs/font-awesome/css/font-awesome.min.css' ),
452
  array(),
453
  fw()->manifest->get_version()
454
  );
 
 
 
 
 
 
 
455
 
456
  wp_register_script(
457
  'backbone-relational',
@@ -499,6 +487,154 @@ final class _FW_Component_Backend {
499
  $this->static_registered = true;
500
  }
501
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
502
  public function _filter_admin_footer_text( $html ) {
503
  if (
504
  (
@@ -856,26 +992,19 @@ final class _FW_Component_Backend {
856
  * @deprecated since 2.5.0
857
  */
858
  public function _sync_post_separate_meta( $post_id ) {
859
- $post_type = get_post_type( $post_id );
860
-
861
- if ( ! $post_type ) {
862
  return false;
863
  }
864
 
865
  $meta_prefix = 'fw_option:';
 
 
866
 
867
- /**
868
- * Collect all options that needs to be saved in separate meta
869
- */
870
  {
871
  $options_values = fw_get_db_post_option( $post_id );
872
 
873
- $separate_meta_options = array();
874
-
875
- foreach (
876
- fw_extract_only_options( fw()->theme->get_post_options( $post_type ) )
877
- as $option_id => $option
878
- ) {
879
  if (
880
  isset( $option['save-in-separate-meta'] )
881
  &&
@@ -883,6 +1012,23 @@ final class _FW_Component_Backend {
883
  &&
884
  array_key_exists( $option_id, $options_values )
885
  ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
886
  $separate_meta_options[ $meta_prefix . $option_id ] = $options_values[ $option_id ];
887
  }
888
  }
@@ -890,9 +1036,7 @@ final class _FW_Component_Backend {
890
  unset( $options_values );
891
  }
892
 
893
- /**
894
- * Delete meta that starts with $meta_prefix
895
- */
896
  {
897
  /** @var wpdb $wpdb */
898
  global $wpdb;
@@ -906,10 +1050,17 @@ final class _FW_Component_Backend {
906
  $wpdb->esc_like( $meta_prefix ) . '%',
907
  $post_id
908
  )
909
- )
910
- as $row
911
  ) {
912
- if ( array_key_exists( $row->meta_key, $separate_meta_options ) ) {
 
 
 
 
 
 
 
 
913
  /**
914
  * This meta exists and will be updated below.
915
  * Do not delete for performance reasons, instead of delete->insert will be performed only update
@@ -1540,12 +1691,12 @@ final class _FW_Component_Backend {
1540
  *
1541
  * @internal
1542
  */
1543
- public function _register_option_type( FW_Access_Key $access_key, $option_type_class ) {
1544
  if ( $access_key->get_key() !== 'fw_option_type' ) {
1545
  trigger_error( 'Call denied', E_USER_ERROR );
1546
  }
1547
 
1548
- $this->register_option_type( $option_type_class );
1549
  }
1550
 
1551
  /**
@@ -1568,29 +1719,16 @@ final class _FW_Component_Backend {
1568
  * @return FW_Option_Type|FW_Option_Type_Undefined
1569
  */
1570
  public function option_type( $option_type ) {
1571
- if ( is_array( $this->option_types_pending_registration ) ) { // This method is called for the first time
1572
- require_once dirname(__FILE__) .'/../extends/class-fw-option-type.php';
1573
-
1574
- do_action('fw_option_types_init');
1575
 
1576
- // Register pending option types
1577
- {
1578
- $pending_option_types = $this->option_types_pending_registration;
1579
-
1580
- // clear this property, so register_option_type() will not add option types to pending anymore
1581
- $this->option_types_pending_registration = false;
1582
-
1583
- foreach ( $pending_option_types as $option_type_class ) {
1584
- $this->register_option_type( $option_type_class );
1585
- }
1586
-
1587
- unset( $pending_option_types );
1588
- }
1589
  }
1590
 
1591
- if ( isset( $this->option_types[ $option_type ] ) ) {
1592
- return $this->option_types[ $option_type ];
1593
- } else {
1594
  if ( is_admin() ) {
1595
  $should_write_flash = apply_filters(
1596
  'fw_backend_undefined_option_type_warn_user',
@@ -1598,7 +1736,7 @@ final class _FW_Component_Backend {
1598
  $option_type
1599
  );
1600
 
1601
- if ($should_write_flash) {
1602
  FW_Flash_Messages::add(
1603
  'fw-get-option-type-undefined-' . $option_type,
1604
  sprintf( __( 'Undefined option type: %s', 'fw' ), $option_type ),
@@ -1607,9 +1745,7 @@ final class _FW_Component_Backend {
1607
  }
1608
  }
1609
 
1610
- if (!$this->undefined_option_type) {
1611
- require_once fw_get_framework_directory('/includes/option-types/class-fw-option-type-undefined.php');
1612
-
1613
  $this->undefined_option_type = new FW_Option_Type_Undefined();
1614
  }
1615
 
@@ -1617,35 +1753,46 @@ final class _FW_Component_Backend {
1617
  }
1618
  }
1619
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1620
  /**
1621
  * @param string $container_type
1622
  *
1623
  * @return FW_Container_Type|FW_Container_Type_Undefined
1624
  */
1625
  public function container_type( $container_type ) {
1626
- if ( is_array( $this->container_types_pending_registration ) ) { // This method is called for the first time
1627
- require_once dirname(__FILE__) .'/../extends/class-fw-container-type.php';
1628
-
1629
- do_action('fw_container_types_init');
1630
-
1631
- // Register pending container types
1632
- {
1633
- $pending_container_types = $this->container_types_pending_registration;
1634
-
1635
- // clear this property, so register_container_type() will not add container types to pending anymore
1636
- $this->container_types_pending_registration = false;
1637
 
1638
- foreach ( $pending_container_types as $container_type_class ) {
1639
- $this->register_container_type( $container_type_class );
1640
- }
1641
-
1642
- unset( $pending_container_types );
1643
- }
1644
  }
1645
 
1646
- if ( isset( $this->container_types[ $container_type ] ) ) {
1647
- return $this->container_types[ $container_type ];
1648
- } else {
1649
  if ( is_admin() ) {
1650
  FW_Flash_Messages::add(
1651
  'fw-get-container-type-undefined-' . $container_type,
@@ -1654,10 +1801,8 @@ final class _FW_Component_Backend {
1654
  );
1655
  }
1656
 
1657
- if (!$this->undefined_container_type) {
1658
- require_once fw_get_framework_directory('/includes/container-types/class-fw-container-type-undefined.php');
1659
-
1660
- $this->undefined_container_type = new FW_Container_Type_Undefined();
1661
  }
1662
 
1663
  return $this->undefined_container_type;
@@ -1844,18 +1989,11 @@ final class _FW_Component_Backend {
1844
  }
1845
  }
1846
 
1847
- if (!class_exists('_FW_Customizer_Setting_Option')) {
1848
- require_once fw_get_framework_directory('/includes/customizer/class--fw-customizer-setting-option.php');
1849
- }
1850
-
1851
- if (!class_exists('_FW_Customizer_Control_Option_Wrapper')) {
1852
- require_once fw_get_framework_directory('/includes/customizer/class--fw-customizer-control-option-wrapper.php');
1853
- }
1854
-
1855
  {
1856
  $args_setting = array(
1857
  'default' => fw()->backend->option_type($opt['option']['type'])->get_value_from_input($opt['option'], null),
1858
  'fw_option' => $opt['option'],
 
1859
  );
1860
 
1861
  if (isset($opt['option']['wp-customizer-setting-args']) && is_array($opt['option']['wp-customizer-setting-args'])) {
@@ -1913,16 +2051,12 @@ final class _FW_Component_Backend {
1913
  *
1914
  * @param bool $fresh_instance Whether to force return a fresh instance of the class
1915
  *
 
 
1916
  * @since 2.6.9
1917
  */
1918
  public function get_markdown_parser($fresh_instance = false) {
1919
  if (! $this->markdown_parser || $fresh_instance) {
1920
- $path = dirname(__FILE__) . '/extensions/manager/includes/parsedown/Parsedown.php';
1921
-
1922
- if (! class_exists('Parsedown')) {
1923
- require_once $path;
1924
- }
1925
-
1926
  $this->markdown_parser = new Parsedown();
1927
  }
1928
 
25
  */
26
  private $markdown_parser = null;
27
 
 
 
 
 
 
 
 
 
28
  /**
29
  * Contains all option types
30
  * @var FW_Option_Type[]
62
  */
63
  private $access_key;
64
 
65
+ private $storage_key = 'fw-option-type';
66
+
67
  /**
68
  * @internal
69
  */
145
  */
146
  public function _init() {
147
  if ( is_admin() ) {
 
148
  $this->settings_form = new FW_Settings_Form_Theme('theme-settings');
149
  }
150
 
210
 
211
  /**
212
  * @param string|FW_Option_Type $option_type_class
213
+ * @param string|null $type
214
  *
215
  * @internal
216
  */
217
+ private function register_option_type( $option_type_class, $type = null ) {
218
+ if ( $type == null ) {
219
+ try {
220
+ $type = $this->get_instance( $option_type_class )->get_type();
221
+ } catch ( FW_Option_Type_Exception_Invalid_Class $exception ) {
222
+ if ( ! is_subclass_of( $option_type_class, 'FW_Option_Type' ) ) {
223
+ trigger_error( 'Invalid option type class ' . get_class( $option_type_class ), E_USER_WARNING );
224
+
225
+ return;
226
+ }
 
 
227
  }
228
+ }
229
 
230
+ if ( isset( $this->option_types[ $type ] ) ) {
 
 
 
 
 
231
  if ( isset( $this->option_types[ $type ] ) ) {
232
  trigger_error( 'Option type "' . $type . '" already registered', E_USER_WARNING );
233
+
234
  return;
235
  }
 
 
 
 
236
  }
237
+
238
+ $this->option_types[$type] = $option_type_class;
239
  }
240
 
241
  /**
242
  * @param string|FW_Container_Type $container_type_class
243
+ * @param string|null $type
244
  *
245
  * @internal
246
  */
247
+ private function register_container_type( $container_type_class, $type = null ) {
248
+ if ( $type == null ) {
249
+ try {
250
+ $type = $this->get_instance( $container_type_class )->get_type();
251
+ } catch ( FW_Option_Type_Exception_Invalid_Class $exception ) {
252
+ if ( ! is_subclass_of( $container_type_class, 'FW_Container_Type' ) ) {
253
+ trigger_error( 'Invalid container type class ' . get_class( $container_type_class ), E_USER_WARNING );
254
+
255
+ return;
256
+ }
 
 
257
  }
258
+ }
259
 
260
+ if ( isset( $this->container_types[ $type ] ) ) {
 
 
 
 
 
261
  if ( isset( $this->container_types[ $type ] ) ) {
262
  trigger_error( 'Container type "' . $type . '" already registered', E_USER_WARNING );
263
+
264
  return;
265
  }
 
 
 
 
266
  }
267
+
268
+ $this->container_types[$type] = $container_type_class;
269
  }
270
 
271
  private function register_static() {
428
  }
429
 
430
  wp_register_style(
431
+ 'font-awesome',
432
  fw_get_framework_directory_uri( '/static/libs/font-awesome/css/font-awesome.min.css' ),
433
  array(),
434
  fw()->manifest->get_version()
435
  );
436
+ /**
437
+ * backwards compatibility, in case extensions are not up-to-date
438
+ * todo: remove in next major version
439
+ * https://github.com/ThemeFuse/Unyson/issues/2198
440
+ * @deprecated
441
+ */
442
+ wp_register_style('fw-font-awesome', fw_get_framework_directory_uri( '/static/libs/font-awesome/css/font-awesome.min.css' ));
443
 
444
  wp_register_script(
445
  'backbone-relational',
487
  $this->static_registered = true;
488
  }
489
 
490
+ /**
491
+ * @param $key
492
+ * @param $type
493
+ * @param $parent_class
494
+ *
495
+ * @return FW_Option_Type|FW_Container_Type
496
+ * @throws FW_Option_Type_Exception
497
+ * @throws FW_Option_Type_Exception_Not_Found
498
+ *
499
+ * @since 2.6.11
500
+ */
501
+ protected function get_item_from_storage( $key, $type, $parent_class ) {
502
+ try {
503
+ $object = FW_Cache::get( "$key:$type" );
504
+ if ( ! is_subclass_of( $object, $parent_class ) ) {
505
+ throw new FW_Option_Type_Exception( $type );
506
+ }
507
+
508
+ return $object;
509
+ } catch ( FW_Cache_Not_Found_Exception $exception ) {
510
+ throw new FW_Option_Type_Exception_Not_Found( $type );
511
+ }
512
+ }
513
+
514
+ /**
515
+ * @param $key
516
+ * @param FW_Option_Type|FW_Container_Type $item
517
+ *
518
+ * @since 2.6.11
519
+ */
520
+ protected function set_item_in_storage( $key, $item ) {
521
+ FW_Cache::set( "$key:{$item->get_type()}", $item );
522
+ }
523
+
524
+ /**
525
+ * @param $type
526
+ *
527
+ * @return FW_Option_Type
528
+ * @throws FW_Option_Type_Exception
529
+ * @throws FW_Option_Type_Exception_Not_Found
530
+ *
531
+ * @since 2.6.11
532
+ */
533
+ protected function get_option_from_storage( $type ) {
534
+ return $this->get_item_from_storage( "$this->storage_key:option-types", $type, 'FW_Option_Type' );
535
+ }
536
+
537
+ /**
538
+ * @param $type
539
+ *
540
+ * @return FW_Container_Type
541
+ * @throws FW_Option_Type_Exception
542
+ * @throws FW_Option_Type_Exception_Not_Found
543
+ *
544
+ * @since 2.6.11
545
+ */
546
+ protected function get_container_from_storage( $type ) {
547
+ return $this->get_item_from_storage( "$this->storage_key:container-types", $type, 'FW_Option_Type' );
548
+ }
549
+
550
+ /**
551
+ * @param FW_Option_Type $option
552
+ *
553
+ * @return FW_Option_Type
554
+ *
555
+ * @since 2.6.11
556
+ */
557
+ protected function set_option_in_storage( FW_Option_Type $option ) {
558
+ $this->set_item_in_storage( "$this->storage_key:option-types", $option );
559
+
560
+ return $option;
561
+ }
562
+
563
+ /**
564
+ * @param FW_Option_Type $option
565
+ *
566
+ * @return FW_Option_Type
567
+ */
568
+ protected function set_container_in_storage( FW_Container_Type $option ) {
569
+ $this->set_item_in_storage( "$this->storage_key:container-types", $option );
570
+
571
+ return $option;
572
+ }
573
+
574
+ /**
575
+ * @param $class
576
+ *
577
+ * @return FW_Option_Type
578
+ * @throws FW_Option_Type_Exception_Invalid_Class
579
+ */
580
+ protected function get_instance( $class ) {
581
+ if ( ! class_exists( $class )
582
+ || (
583
+ ! is_subclass_of( $class, 'FW_Option_Type' )
584
+ &&
585
+ ! is_subclass_of( $class, 'FW_Container_Type' )
586
+ )
587
+ ) {
588
+ throw new FW_Option_Type_Exception_Invalid_Class( $class );
589
+ }
590
+
591
+ return new $class;
592
+ }
593
+
594
+ /**
595
+ * @param $type
596
+ *
597
+ * @return FW_Option_Type
598
+ * @throws FW_Option_Type_Exception
599
+ * @throws FW_Option_Type_Exception_Not_Found
600
+ * @throws FW_Option_Type_Exception_Invalid_Class
601
+ */
602
+ protected function get_option_type( $type ) {
603
+ try {
604
+ return $this->get_option_from_storage( $type );
605
+ } catch ( FW_Option_Type_Exception $exception ) {
606
+ if ( isset( $this->option_types[ $type ] ) ) {
607
+ $option = $this->get_instance( $this->option_types[ $type ] );
608
+ $option->_call_init( $this->get_access_key() );
609
+
610
+ return $this->set_option_in_storage( $option );
611
+ }
612
+ throw new FW_Option_Type_Exception_Not_Found( $type );
613
+ }
614
+ }
615
+
616
+ /**
617
+ * @param $type
618
+ *
619
+ * @return FW_Container_Type
620
+ * @throws FW_Option_Type_Exception
621
+ * @throws FW_Option_Type_Exception_Not_Found
622
+ * @throws FW_Option_Type_Exception_Invalid_Class
623
+ */
624
+ protected function get_container_type( $type ) {
625
+ try {
626
+ return $this->get_container_from_storage( $type );
627
+ } catch ( FW_Option_Type_Exception $exception ) {
628
+ if ( isset( $this->container_types[ $type ] ) ) {
629
+ $option = $this->get_instance( $this->container_types[ $type ] );
630
+ $option->_call_init( $this->get_access_key() );
631
+
632
+ return $this->set_container_in_storage( $option );
633
+ }
634
+ throw new FW_Option_Type_Exception_Not_Found( $type );
635
+ }
636
+ }
637
+
638
  public function _filter_admin_footer_text( $html ) {
639
  if (
640
  (
992
  * @deprecated since 2.5.0
993
  */
994
  public function _sync_post_separate_meta( $post_id ) {
995
+ if ( ! ( $post_type = get_post_type( $post_id ) ) ) {
 
 
996
  return false;
997
  }
998
 
999
  $meta_prefix = 'fw_option:';
1000
+ $only_options = fw_extract_only_options( fw()->theme->get_post_options( $post_type ) );
1001
+ $separate_meta_options = array();
1002
 
1003
+ // Collect all options that needs to be saved in separate meta
 
 
1004
  {
1005
  $options_values = fw_get_db_post_option( $post_id );
1006
 
1007
+ foreach ($only_options as $option_id => $option) {
 
 
 
 
 
1008
  if (
1009
  isset( $option['save-in-separate-meta'] )
1010
  &&
1012
  &&
1013
  array_key_exists( $option_id, $options_values )
1014
  ) {
1015
+ if (defined('WP_DEBUG') && WP_DEBUG) {
1016
+ FW_Flash_Messages::add(
1017
+ 'save-in-separate-meta:deprecated',
1018
+ '<p>The <code>save-in-separate-meta</code> option parameter is <strong>deprecated</strong>.</p>'
1019
+ .'<p>Please replace</p>'
1020
+ .'<pre>\'save-in-separate-meta\' => true</pre>'
1021
+ .'<p>with</p>'
1022
+ .'<pre>\'fw-storage\' => array('
1023
+ ."\n 'type' => 'post-meta',"
1024
+ ."\n 'post-meta' => 'fw_option:{your-option-id}',"
1025
+ ."\n)</pre>"
1026
+ .'<p>in <code>{theme}'. fw_get_framework_customizations_dir_rel_path('/theme/options/posts/'. $post_type .'.php') .'</code></p>'
1027
+ .'<p><a href="'. esc_attr('http://manual.unyson.io/en/latest/options/storage.html#content') .'" target="_blank">'. esc_html__('Info about fw-storage', 'fw') .'</a></p>',
1028
+ 'warning'
1029
+ );
1030
+ }
1031
+
1032
  $separate_meta_options[ $meta_prefix . $option_id ] = $options_values[ $option_id ];
1033
  }
1034
  }
1036
  unset( $options_values );
1037
  }
1038
 
1039
+ // Delete meta that starts with $meta_prefix
 
 
1040
  {
1041
  /** @var wpdb $wpdb */
1042
  global $wpdb;
1050
  $wpdb->esc_like( $meta_prefix ) . '%',
1051
  $post_id
1052
  )
1053
+ ) as $row
 
1054
  ) {
1055
+ if (
1056
+ array_key_exists( $row->meta_key, $separate_meta_options )
1057
+ ||
1058
+ ( // skip options containing 'fw-storage'
1059
+ ($option_id = substr($row->meta_key, 10))
1060
+ &&
1061
+ isset($only_options[$option_id]['fw-storage'])
1062
+ )
1063
+ ) {
1064
  /**
1065
  * This meta exists and will be updated below.
1066
  * Do not delete for performance reasons, instead of delete->insert will be performed only update
1691
  *
1692
  * @internal
1693
  */
1694
+ public function _register_option_type( FW_Access_Key $access_key, $option_type_class, $type= null ) {
1695
  if ( $access_key->get_key() !== 'fw_option_type' ) {
1696
  trigger_error( 'Call denied', E_USER_ERROR );
1697
  }
1698
 
1699
+ $this->register_option_type( $option_type_class, $type );
1700
  }
1701
 
1702
  /**
1719
  * @return FW_Option_Type|FW_Option_Type_Undefined
1720
  */
1721
  public function option_type( $option_type ) {
1722
+ static $did_action = false;
 
 
 
1723
 
1724
+ if ( ! $did_action ) {
1725
+ do_action( 'fw_option_types_init' );
1726
+ $did_action = true;
 
 
 
 
 
 
 
 
 
 
1727
  }
1728
 
1729
+ try {
1730
+ return $this->get_option_type( $option_type );
1731
+ } catch ( FW_Option_Type_Exception_Not_Found $exception ) {
1732
  if ( is_admin() ) {
1733
  $should_write_flash = apply_filters(
1734
  'fw_backend_undefined_option_type_warn_user',
1736
  $option_type
1737
  );
1738
 
1739
+ if ( $should_write_flash ) {
1740
  FW_Flash_Messages::add(
1741
  'fw-get-option-type-undefined-' . $option_type,
1742
  sprintf( __( 'Undefined option type: %s', 'fw' ), $option_type ),
1745
  }
1746
  }
1747
 
1748
+ if ( ! $this->undefined_option_type ) {
 
 
1749
  $this->undefined_option_type = new FW_Option_Type_Undefined();
1750
  }
1751
 
1753
  }
1754
  }
1755
 
1756
+ /**
1757
+ * Return an array with all option types names
1758
+ *
1759
+ * @return array
1760
+ *
1761
+ * @since 2.6.11
1762
+ */
1763
+ public function get_option_types() {
1764
+ $this->option_type('text'); // trigger init
1765
+ return array_keys( $this->option_types );
1766
+ }
1767
+
1768
+ /**
1769
+ * Return an array with all container types names
1770
+ *
1771
+ * @return array
1772
+ *
1773
+ * @since 2.6.11
1774
+ */
1775
+ public function get_container_types() {
1776
+ $this->container_type('box'); // trigger init
1777
+ return array_keys( $this->container_types );
1778
+ }
1779
+
1780
  /**
1781
  * @param string $container_type
1782
  *
1783
  * @return FW_Container_Type|FW_Container_Type_Undefined
1784
  */
1785
  public function container_type( $container_type ) {
1786
+ static $did_action = false;
 
 
 
 
 
 
 
 
 
 
1787
 
1788
+ if ( ! $did_action ) {
1789
+ do_action( 'fw_container_types_init' );
1790
+ $did_action = true;
 
 
 
1791
  }
1792
 
1793
+ try {
1794
+ return $this->get_container_type( $container_type );
1795
+ } catch ( FW_Option_Type_Exception_Not_Found $exception ) {
1796
  if ( is_admin() ) {
1797
  FW_Flash_Messages::add(
1798
  'fw-get-container-type-undefined-' . $container_type,
1801
  );
1802
  }
1803
 
1804
+ if ( ! $this->undefined_option_type ) {
1805
+ $this->undefined_option_type = new FW_Container_Type_Undefined();
 
 
1806
  }
1807
 
1808
  return $this->undefined_container_type;
1989
  }
1990
  }
1991
 
 
 
 
 
 
 
 
 
1992
  {
1993
  $args_setting = array(
1994
  'default' => fw()->backend->option_type($opt['option']['type'])->get_value_from_input($opt['option'], null),
1995
  'fw_option' => $opt['option'],
1996
+ 'fw_option_id' => $opt['id'],
1997
  );
1998
 
1999
  if (isset($opt['option']['wp-customizer-setting-args']) && is_array($opt['option']['wp-customizer-setting-args'])) {
2051
  *
2052
  * @param bool $fresh_instance Whether to force return a fresh instance of the class
2053
  *
2054
+ * @return Parsedown
2055
+ *
2056
  * @since 2.6.9
2057
  */
2058
  public function get_markdown_parser($fresh_instance = false) {
2059
  if (! $this->markdown_parser || $fresh_instance) {
 
 
 
 
 
 
2060
  $this->markdown_parser = new Parsedown();
2061
  }
2062
 
framework/core/components/extensions.php CHANGED
@@ -91,11 +91,7 @@ final class _FW_Component_Extensions
91
  }
92
  }
93
 
94
- public function __construct()
95
- {
96
- require dirname(__FILE__) .'/extensions/class-fw-extension-default.php';
97
-
98
- require dirname(__FILE__) .'/extensions/manager/class--fw-extensions-manager.php';
99
  $this->manager = new _FW_Extensions_Manager();
100
  }
101
 
@@ -150,13 +146,7 @@ final class _FW_Component_Extensions
150
  $data['parent'] = null;
151
  }
152
 
153
- try {
154
- $dirs = FW_File_Cache::get($cache_key = 'core:ext:load:glob:'. $data['path']);
155
- } catch (FW_File_Cache_Not_Found_Exception $e) {
156
- $dirs = glob($data['path'] .'/*', GLOB_ONLYDIR);
157
-
158
- FW_File_Cache::set($cache_key, $dirs);
159
- }
160
 
161
  if (empty($dirs)) {
162
  return;
@@ -298,13 +288,7 @@ final class _FW_Component_Extensions
298
  }
299
 
300
  foreach ($paths as $path => $uri) {
301
- try {
302
- $files = FW_File_Cache::get($cache_key = 'core:ext:glob:inc-all-php:'. $extension->get_name() .':'. $path);
303
- } catch (FW_File_Cache_Not_Found_Exception $e) {
304
- $files = glob($path . $dir_rel_path .'/*.php');
305
-
306
- FW_File_Cache::set($cache_key, $files);
307
- }
308
 
309
  if ($files) {
310
  foreach ($files as $dir_file_path) {
91
  }
92
  }
93
 
94
+ public function __construct() {
 
 
 
 
95
  $this->manager = new _FW_Extensions_Manager();
96
  }
97
 
146
  $data['parent'] = null;
147
  }
148
 
149
+ $dirs = glob($data['path'] .'/*', GLOB_ONLYDIR);
 
 
 
 
 
 
150
 
151
  if (empty($dirs)) {
152
  return;
288
  }
289
 
290
  foreach ($paths as $path => $uri) {
291
+ $files = glob($path . $dir_rel_path .'/*.php');
 
 
 
 
 
 
292
 
293
  if ($files) {
294
  foreach ($files as $dir_file_path) {
framework/core/components/extensions/manager/class--fw-extensions-manager.php CHANGED
@@ -202,9 +202,6 @@ final class _FW_Extensions_Manager
202
  $theme_available_ext_file = fw_fix_path(get_template_directory())
203
  . fw_get_framework_customizations_dir_rel_path( '/theme/available-extensions.php' )
204
  )) {
205
- require_once dirname( __FILE__ ) . '/includes/available-ext/class--fw-available-extensions-register.php';
206
- require_once dirname( __FILE__ ) . '/includes/available-ext/class-fw-available-extension.php';
207
-
208
  $register = new _FW_Available_Extensions_Register(self::get_access_key()->get_key());
209
 
210
  /**
@@ -964,12 +961,6 @@ final class _FW_Extensions_Manager
964
  }
965
 
966
  {
967
- if (!class_exists('_FW_Extensions_Install_Upgrader_Skin')) {
968
- fw_include_file_isolated(
969
- dirname(__FILE__) .'/includes/class--fw-extensions-install-upgrader-skin.php'
970
- );
971
- }
972
-
973
  $skin = new _FW_Extensions_Install_Upgrader_Skin(array(
974
  'title' => $supported
975
  ? _n('Install Compatible Extension', 'Install Compatible Extensions', count($extensions), 'fw')
@@ -1474,12 +1465,6 @@ final class _FW_Extensions_Manager
1474
  $extensions = array_fill_keys(array_map('trim', explode(',', FW_Request::GET('extension', ''))), array());
1475
 
1476
  {
1477
- if (!class_exists('_FW_Extensions_Delete_Upgrader_Skin')) {
1478
- fw_include_file_isolated(
1479
- dirname(__FILE__) .'/includes/class--fw-extensions-delete-upgrader-skin.php'
1480
- );
1481
- }
1482
-
1483
  $skin = new _FW_Extensions_Delete_Upgrader_Skin(array(
1484
  'title' => _n('Delete Extension', 'Delete Extensions', count($extensions), 'fw'),
1485
  ));
@@ -2464,9 +2449,6 @@ final class _FW_Extensions_Manager
2464
  }
2465
  }
2466
 
2467
- require_once dirname( __FILE__ ) . '/includes/download-source/class--fw-ext-download-source.php';
2468
- require_once dirname( __FILE__ ) . '/includes/download-source/class--fw-ext-download-source-register.php';
2469
-
2470
  require_once dirname( __FILE__ ) . '/includes/download-source/types/init.php';
2471
 
2472
  $register = new _FW_Ext_Download_Source_Register(self::get_access_key()->get_key());
@@ -2970,7 +2952,7 @@ final class _FW_Extensions_Manager
2970
  $this->get_uri('/static/extensions-page.css'),
2971
  array(
2972
  'fw',
2973
- 'fw-unycon', 'fw-font-awesome', // in case some extension has font-icon thumbnail
2974
  ),
2975
  fw()->manifest->get_version()
2976
  );
202
  $theme_available_ext_file = fw_fix_path(get_template_directory())
203
  . fw_get_framework_customizations_dir_rel_path( '/theme/available-extensions.php' )
204
  )) {
 
 
 
205
  $register = new _FW_Available_Extensions_Register(self::get_access_key()->get_key());
206
 
207
  /**
961
  }
962
 
963
  {
 
 
 
 
 
 
964
  $skin = new _FW_Extensions_Install_Upgrader_Skin(array(
965
  'title' => $supported
966
  ? _n('Install Compatible Extension', 'Install Compatible Extensions', count($extensions), 'fw')
1465
  $extensions = array_fill_keys(array_map('trim', explode(',', FW_Request::GET('extension', ''))), array());
1466
 
1467
  {
 
 
 
 
 
 
1468
  $skin = new _FW_Extensions_Delete_Upgrader_Skin(array(
1469
  'title' => _n('Delete Extension', 'Delete Extensions', count($extensions), 'fw'),
1470
  ));
2449
  }
2450
  }
2451
 
 
 
 
2452
  require_once dirname( __FILE__ ) . '/includes/download-source/types/init.php';
2453
 
2454
  $register = new _FW_Ext_Download_Source_Register(self::get_access_key()->get_key());
2952
  $this->get_uri('/static/extensions-page.css'),
2953
  array(
2954
  'fw',
2955
+ 'fw-unycon', 'font-awesome', // in case some extension has font-icon thumbnail
2956
  ),
2957
  fw()->manifest->get_version()
2958
  );
framework/core/components/extensions/manager/includes/class--fw-extensions-delete-upgrader-skin.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php if (!defined('FW')) die('Forbidden');
2
 
3
- require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skins.php';
4
 
5
  class _FW_Extensions_Delete_Upgrader_Skin extends WP_Upgrader_Skin
6
  {
1
  <?php if (!defined('FW')) die('Forbidden');
2
 
3
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
4
 
5
  class _FW_Extensions_Delete_Upgrader_Skin extends WP_Upgrader_Skin
6
  {
framework/core/components/extensions/manager/includes/class--fw-extensions-install-upgrader-skin.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php if (!defined('FW')) die('Forbidden');
2
 
3
- require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skins.php';
4
 
5
  class _FW_Extensions_Install_Upgrader_Skin extends WP_Upgrader_Skin
6
  {
1
  <?php if (!defined('FW')) die('Forbidden');
2
 
3
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
4
 
5
  class _FW_Extensions_Install_Upgrader_Skin extends WP_Upgrader_Skin
6
  {
framework/core/components/extensions/manager/includes/download-source/types/init.php CHANGED
@@ -2,9 +2,6 @@
2
 
3
  if ( ! function_exists( '_action_fw_register_ext_download_sources' ) ) {
4
  function _action_fw_register_ext_download_sources(_FW_Ext_Download_Source_Register $download_sources) {
5
- $dir = dirname(__FILE__);
6
-
7
- require_once $dir . '/class-fw-download-source-github.php';
8
  $download_sources->register(new FW_Ext_Download_Source_Github());
9
  }
10
  }
2
 
3
  if ( ! function_exists( '_action_fw_register_ext_download_sources' ) ) {
4
  function _action_fw_register_ext_download_sources(_FW_Ext_Download_Source_Register $download_sources) {
 
 
 
5
  $download_sources->register(new FW_Ext_Download_Source_Github());
6
  }
7
  }
framework/core/components/theme.php CHANGED
@@ -46,20 +46,12 @@ final class _FW_Component_Theme
46
  */
47
  public function locate_path($rel_path)
48
  {
49
- try {
50
- return FW_File_Cache::get($cache_key = 'core:theme:path:'. $rel_path);
51
- } catch (FW_File_Cache_Not_Found_Exception $e) {
52
- if (is_child_theme() && file_exists(fw_get_stylesheet_customizations_directory('/theme'. $rel_path))) {
53
- $path = fw_get_stylesheet_customizations_directory('/theme'. $rel_path);
54
- } elseif (file_exists(fw_get_template_customizations_directory('/theme'. $rel_path))) {
55
- $path = fw_get_template_customizations_directory('/theme'. $rel_path);
56
- } else {
57
- $path = false;
58
- }
59
-
60
- FW_File_Cache::set($cache_key, $path);
61
-
62
- return $path;
63
  }
64
  }
65
 
46
  */
47
  public function locate_path($rel_path)
48
  {
49
+ if (is_child_theme() && file_exists(fw_get_stylesheet_customizations_directory('/theme'. $rel_path))) {
50
+ return fw_get_stylesheet_customizations_directory('/theme'. $rel_path);
51
+ } elseif (file_exists(fw_get_template_customizations_directory('/theme'. $rel_path))) {
52
+ return fw_get_template_customizations_directory('/theme'. $rel_path);
53
+ } else {
54
+ return false;
 
 
 
 
 
 
 
 
55
  }
56
  }
57
 
framework/core/exceptions/class-fw-option-type-exception.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( ! defined( 'FW' ) ) {
2
+ die( 'Forbidden' );
3
+ }
4
+
5
+
6
+ /**
7
+ * Class FW_Option_Type_Exception
8
+ *
9
+ * @since 2.6.11
10
+ */
11
+ class FW_Option_Type_Exception extends Exception {
12
+
13
+ }
14
+
15
+ /**
16
+ * Class FW_Option_Type_Exception_Not_Found
17
+ *
18
+ * @since 2.6.11
19
+ */
20
+ class FW_Option_Type_Exception_Not_Found extends FW_Option_Type_Exception {
21
+
22
+ }
23
+
24
+ /**
25
+ * Class FW_Option_Type_Exception_Invalid_Class
26
+ *
27
+ * @since 2.6.11
28
+ */
29
+ class FW_Option_Type_Exception_Invalid_Class extends FW_Option_Type_Exception {
30
+
31
+ }
32
+
33
+ /**
34
+ * Class FW_Option_Type_Exception_Already_Registered
35
+ *
36
+ * @since 2.6.11
37
+ */
38
+ class FW_Option_Type_Exception_Already_Registered extends FW_Option_Type_Exception {
39
+
40
+ }
framework/core/extends/class-fw-extension.php CHANGED
@@ -141,26 +141,15 @@ abstract class FW_Extension
141
  */
142
  final public function locate_path($rel_path)
143
  {
144
- try {
145
- return FW_File_Cache::get($cache_key = 'ext:'. $this->get_name() .':path:'. $rel_path);
146
- } catch (FW_File_Cache_Not_Found_Exception $e) {
147
- $result = false;
148
- $locations = $this->customizations_locations;
149
- $locations[$this->get_path()] = $this->get_uri();
150
 
151
- foreach ($locations as $path => $uri) {
152
- if (file_exists($path . $rel_path)) {
153
- $result = $path . $rel_path;
154
- break;
155
- }
156
  }
157
-
158
- FW_File_Cache::set($cache_key, $result);
159
-
160
- return $result;
161
  }
162
 
163
-
164
  return false;
165
  }
166
 
@@ -170,24 +159,16 @@ abstract class FW_Extension
170
  */
171
  final public function locate_URI($rel_path)
172
  {
173
- try {
174
- return FW_File_Cache::get($cache_key = 'ext:'. $this->get_name() .':uri:'. $rel_path);
175
- } catch (FW_File_Cache_Not_Found_Exception $e) {
176
- $result = false;
177
- $locations = $this->customizations_locations;
178
- $locations[$this->get_path()] = $this->get_uri();
179
 
180
- foreach ($locations as $path => $uri) {
181
- if (file_exists($path . $rel_path)) {
182
- $result = $uri . $rel_path;
183
- break;
184
- }
185
  }
186
-
187
- FW_File_Cache::set($cache_key, $result);
188
-
189
- return $result;
190
  }
 
 
191
  }
192
 
193
  /**
141
  */
142
  final public function locate_path($rel_path)
143
  {
144
+ $locations = $this->customizations_locations;
145
+ $locations[$this->get_path()] = $this->get_uri();
 
 
 
 
146
 
147
+ foreach ($locations as $path => $uri) {
148
+ if (file_exists($path . $rel_path)) {
149
+ return $path . $rel_path;
 
 
150
  }
 
 
 
 
151
  }
152
 
 
153
  return false;
154
  }
155
 
159
  */
160
  final public function locate_URI($rel_path)
161
  {
162
+ $locations = $this->customizations_locations;
163
+ $locations[$this->get_path()] = $this->get_uri();
 
 
 
 
164
 
165
+ foreach ($locations as $path => $uri) {
166
+ if (file_exists($path . $rel_path)) {
167
+ return $uri . $rel_path;
 
 
168
  }
 
 
 
 
169
  }
170
+
171
+ return false;
172
  }
173
 
174
  /**
framework/core/extends/class-fw-option-type.php CHANGED
@@ -5,6 +5,11 @@
5
  */
6
  abstract class FW_Option_Type
7
  {
 
 
 
 
 
8
  /**
9
  * Option's unique type, used in option array in 'type' key
10
  * @return string
@@ -88,11 +93,6 @@ abstract class FW_Option_Type
88
  return fw()->backend->get_options_name_attr_prefix();
89
  }
90
 
91
- final public function __construct()
92
- {
93
- // does nothing at the moment, but maybe in the future will do something
94
- }
95
-
96
  /**
97
  * @param FW_Access_Key $access_key
98
  * @internal
@@ -311,16 +311,11 @@ abstract class FW_Option_Type
311
 
312
  /**
313
  * Use this method to register a new option type
 
314
  * @param string|FW_Option_Type $option_type_class
315
  */
316
- final public static function register($option_type_class) {
317
- static $registration_access_key = null;
318
-
319
- if ($registration_access_key === null) {
320
- $registration_access_key = new FW_Access_Key('fw_option_type');
321
- }
322
-
323
- fw()->backend->_register_option_type($registration_access_key, $option_type_class);
324
  }
325
 
326
  /**
@@ -400,4 +395,12 @@ abstract class FW_Option_Type
400
  protected function _storage_save($id, array $option, $value, array $params) {
401
  return fw_db_option_storage_save($id, $option, $value, $params);
402
  }
 
 
 
 
 
 
 
 
403
  }
5
  */
6
  abstract class FW_Option_Type
7
  {
8
+ /**
9
+ * @var FW_Access_Key
10
+ */
11
+ private static $access_key;
12
+
13
  /**
14
  * Option's unique type, used in option array in 'type' key
15
  * @return string
93
  return fw()->backend->get_options_name_attr_prefix();
94
  }
95
 
 
 
 
 
 
96
  /**
97
  * @param FW_Access_Key $access_key
98
  * @internal
311
 
312
  /**
313
  * Use this method to register a new option type
314
+ *
315
  * @param string|FW_Option_Type $option_type_class
316
  */
317
+ final public static function register( $option_type_class, $type = null ) {
318
+ fw()->backend->_register_option_type( self::get_access_key(), $option_type_class, $type );
 
 
 
 
 
 
319
  }
320
 
321
  /**
395
  protected function _storage_save($id, array $option, $value, array $params) {
396
  return fw_db_option_storage_save($id, $option, $value, $params);
397
  }
398
+
399
+ private static function get_access_key() {
400
+ if ( self::$access_key === null ) {
401
+ self::$access_key = new FW_Access_Key( 'fw_option_type' );
402
+ }
403
+
404
+ return self::$access_key;
405
+ }
406
  }
framework/extensions/update/includes/classes/class--fw-ext-update-extensions-upgrader-skin.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php if (!defined('FW')) die('Forbidden');
2
 
3
- require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skins.php';
4
 
5
  class _FW_Ext_Update_Extensions_Upgrader_Skin extends WP_Upgrader_Skin
6
  {
1
  <?php if (!defined('FW')) die('Forbidden');
2
 
3
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
4
 
5
  class _FW_Ext_Update_Extensions_Upgrader_Skin extends WP_Upgrader_Skin
6
  {
framework/extensions/update/includes/classes/class--fw-ext-update-framework-upgrader-skin.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php if (!defined('FW')) die('Forbidden');
2
 
3
- require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skins.php';
4
 
5
  class _FW_Ext_Update_Framework_Upgrader_Skin extends WP_Upgrader_Skin
6
  {
1
  <?php if (!defined('FW')) die('Forbidden');
2
 
3
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
4
 
5
  class _FW_Ext_Update_Framework_Upgrader_Skin extends WP_Upgrader_Skin
6
  {
framework/extensions/update/includes/classes/class--fw-ext-update-theme-upgrader-skin.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php if (!defined('FW')) die('Forbidden');
2
 
3
- require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skins.php';
4
 
5
  class _FW_Ext_Update_Theme_Upgrader_Skin extends WP_Upgrader_Skin
6
  {
1
  <?php if (!defined('FW')) die('Forbidden');
2
 
3
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
4
 
5
  class _FW_Ext_Update_Theme_Upgrader_Skin extends WP_Upgrader_Skin
6
  {
framework/extensions/update/manifest.php CHANGED
@@ -6,5 +6,5 @@ $manifest['name'] = __('Update', 'fw');
6
  $manifest['description'] = __('Keep you framework, extensions and theme up to date.', 'fw');
7
  $manifest['standalone'] = true;
8
 
9
- $manifest['version'] = '1.0.11';
10
  $manifest['github_update'] = 'ThemeFuse/Unyson-Update-Extension';
6
  $manifest['description'] = __('Keep you framework, extensions and theme up to date.', 'fw');
7
  $manifest['standalone'] = true;
8
 
9
+ $manifest['version'] = '1.0.12';
10
  $manifest['github_update'] = 'ThemeFuse/Unyson-Update-Extension';
framework/helpers/class-fw-flash-messages.php CHANGED
@@ -113,6 +113,10 @@ class FW_Flash_Messages
113
  */
114
  public static function _print_backend()
115
  {
 
 
 
 
116
  self::process_pending_remove_ids();
117
 
118
  $html = array_fill_keys(array_keys(self::$available_types), '');
113
  */
114
  public static function _print_backend()
115
  {
116
+ if (!session_id()) {
117
+ return; // fixes https://github.com/ThemeFuse/Unyson/issues/2219
118
+ }
119
+
120
  self::process_pending_remove_ids();
121
 
122
  $html = array_fill_keys(array_keys(self::$available_types), '');
framework/helpers/fw-storage.php CHANGED
@@ -49,6 +49,19 @@ function fw_db_option_storage_load($id, array $option, $value, array $params = a
49
  if (
50
  !empty($option['fw-storage'])
51
  &&
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  ($storage = is_array($option['fw-storage'])
53
  ? $option['fw-storage']
54
  : array('type' => $option['fw-storage'])
@@ -77,24 +90,13 @@ function fw_db_option_storage_type($type = null) {
77
  static $types = null;
78
 
79
  if (is_null($types)) {
80
- $dir = fw_get_framework_directory('/includes/option-storage');
81
-
82
- if (!class_exists('FW_Option_Storage_Type')) {
83
- require_once $dir .'/class-fw-option-storage-type.php';
84
- }
85
- if (!class_exists('_FW_Option_Storage_Type_Register')) {
86
- require_once $dir .'/class--fw-option-storage-type-register.php';
87
- }
88
-
89
  $access_key = new FW_Access_Key('fw:option-storage-register');
90
  $register = new _FW_Option_Storage_Type_Register($access_key->get_key());
91
 
92
  {
93
- require_once $dir .'/type/class-fw-option-storage-type-post-meta.php';
94
- $register->register(new FW_Option_Storage_Type_Post_Meta());
95
-
96
- require_once $dir .'/type/class-fw-option-storage-type-wp-option.php';
97
  $register->register(new FW_Option_Storage_Type_WP_Option());
 
 
98
  }
99
 
100
  do_action('fw:option-storage-types:register', $register);
49
  if (
50
  !empty($option['fw-storage'])
51
  &&
52
+ // fixes https://github.com/ThemeFuse/Unyson/issues/2265#issuecomment-268829683
53
+ // do nothing if there is a POST preview value for this option
54
+ // fixme: https://github.com/ThemeFuse/Unyson/issues/2265#issuecomment-269019736
55
+ /*!(
56
+ isset($params['customizer'])
57
+ &&
58
+ is_customize_preview()
59
+ &&
60
+ isset($_POST['customized'])
61
+ &&
62
+ strpos($_POST['customized'], '\"fw_options['. $id .']') !== false
63
+ )
64
+ &&*/
65
  ($storage = is_array($option['fw-storage'])
66
  ? $option['fw-storage']
67
  : array('type' => $option['fw-storage'])
90
  static $types = null;
91
 
92
  if (is_null($types)) {
 
 
 
 
 
 
 
 
 
93
  $access_key = new FW_Access_Key('fw:option-storage-register');
94
  $register = new _FW_Option_Storage_Type_Register($access_key->get_key());
95
 
96
  {
 
 
 
 
97
  $register->register(new FW_Option_Storage_Type_WP_Option());
98
+ $register->register(new FW_Option_Storage_Type_Post_Meta());
99
+ $register->register(new FW_Option_Storage_Type_Term_Meta());
100
  }
101
 
102
  do_action('fw:option-storage-types:register', $register);
framework/helpers/general.php CHANGED
@@ -1,6 +1,154 @@
1
  <?php if (!defined('FW')) die('Forbidden');
2
  // Useful functions
3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  /**
5
  * Recursively find a key's value in array
6
  *
@@ -487,20 +635,12 @@ function fw_current_screen_match(array $rules) {
487
  * @return string URI
488
  */
489
  function fw_locate_theme_path_uri($rel_path) {
490
- try {
491
- return FW_File_Cache::get($cache_key = 'theme-uri:'. $rel_path);
492
- } catch (FW_File_Cache_Not_Found_Exception $e) {
493
- if (is_child_theme() && file_exists(get_stylesheet_directory() . $rel_path)) {
494
- $result = get_stylesheet_directory_uri() . $rel_path;
495
- } elseif (file_exists(get_template_directory() . $rel_path)) {
496
- $result = get_template_directory_uri() . $rel_path;
497
- } else {
498
- $result = 'about:blank#theme-file-not-found:'. $rel_path;
499
- }
500
-
501
- FW_File_Cache::set($cache_key, $result);
502
-
503
- return $result;
504
  }
505
  }
506
 
@@ -511,20 +651,12 @@ function fw_locate_theme_path_uri($rel_path) {
511
  * @return string URI
512
  */
513
  function fw_locate_theme_path($rel_path) {
514
- try {
515
- return FW_File_Cache::get($cache_key = 'theme-path:'. $rel_path);
516
- } catch (FW_File_Cache_Not_Found_Exception $e) {
517
- if (is_child_theme() && file_exists(get_stylesheet_directory() . $rel_path)) {
518
- $result = get_stylesheet_directory() . $rel_path;
519
- } elseif (file_exists(get_template_directory() . $rel_path)) {
520
- $result = get_template_directory() . $rel_path;
521
- } else {
522
- $result = false;
523
- }
524
-
525
- FW_File_Cache::set($cache_key, $result);
526
-
527
- return $result;
528
  }
529
  }
530
 
@@ -1347,11 +1479,13 @@ function fw_oembed_get($url, $args = array()) {
1347
  if (!empty($args['width']) and !empty($args['height']) and class_exists('DOMDocument') and !empty($html)) {
1348
  $dom_element = new DOMDocument();
1349
  @$dom_element->loadHTML($html);
1350
- $obj = $dom_element->getElementsByTagName('iframe')->item(0);
1351
- $obj->setAttribute('width', $args['width']);
1352
- $obj->setAttribute('height', $args['height']);
1353
- //saveXml instead of SaveHTML for php version compatibility
1354
- $html = $dom_element->saveXML($obj, LIBXML_NOEMPTYTAG);
 
 
1355
  }
1356
 
1357
  return $html;
@@ -1367,8 +1501,7 @@ function fw_oembed_get($url, $args = array()) {
1367
  * http://www.zimuel.it/en/strong-cryptography-in-php/
1368
  * > Don't use rand() or mt_rand()
1369
  */
1370
- function fw_secure_rand($length)
1371
- {
1372
  if (function_exists('openssl_random_pseudo_bytes')) {
1373
  $rnd = openssl_random_pseudo_bytes($length, $strong);
1374
  if ($strong) {
@@ -1510,7 +1643,6 @@ function fw_make_stylesheet_portable($href, $contents = null) {
1510
  * @return array|bool
1511
  */
1512
  function fw_get_image_sizes( $size = '' ) {
1513
-
1514
  global $_wp_additional_image_sizes;
1515
 
1516
  $sizes = array();
@@ -1518,34 +1650,26 @@ function fw_get_image_sizes( $size = '' ) {
1518
 
1519
  // Create the full array with sizes and crop info
1520
  foreach( $get_intermediate_image_sizes as $_size ) {
1521
-
1522
  if ( in_array( $_size, array( 'thumbnail', 'medium', 'large' ) ) ) {
1523
-
1524
  $sizes[ $_size ]['width'] = get_option( $_size . '_size_w' );
1525
  $sizes[ $_size ]['height'] = get_option( $_size . '_size_h' );
1526
  $sizes[ $_size ]['crop'] = (bool) get_option( $_size . '_crop' );
1527
-
1528
  } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
1529
-
1530
  $sizes[ $_size ] = array(
1531
  'width' => $_wp_additional_image_sizes[ $_size ]['width'],
1532
  'height' => $_wp_additional_image_sizes[ $_size ]['height'],
1533
  'crop' => $_wp_additional_image_sizes[ $_size ]['crop']
1534
  );
1535
-
1536
  }
1537
-
1538
  }
1539
 
1540
  // Get only 1 size if found
1541
  if ( $size ) {
1542
-
1543
  if( isset( $sizes[ $size ] ) ) {
1544
  return $sizes[ $size ];
1545
  } else {
1546
  return false;
1547
  }
1548
-
1549
  }
1550
 
1551
  return $sizes;
@@ -1675,3 +1799,39 @@ if ( ! function_exists( 'fw_resize' ) ) {
1675
  return ( ! is_wp_error( $response ) && ! empty( $response['src'] ) ) ? $response['src'] : $url;
1676
  }
1677
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php if (!defined('FW')) die('Forbidden');
2
  // Useful functions
3
 
4
+ /**
5
+ * Convert to Unix style directory separators
6
+ */
7
+ function fw_fix_path($path) {
8
+ $fixed_path = untrailingslashit( str_replace(array('//', '\\'), array('/', '/'), $path) );
9
+
10
+ if (empty($fixed_path) && !empty($path)) {
11
+ $fixed_path = '/';
12
+ }
13
+
14
+ return $fixed_path;
15
+ }
16
+
17
+ /**
18
+ * Relative path of the framework customizations directory
19
+ * @param string $append
20
+ * @return string
21
+ */
22
+ function fw_get_framework_customizations_dir_rel_path($append = '') {
23
+ try {
24
+ $dir = FW_Cache::get($cache_key = 'fw_customizations_dir_rel_path');
25
+ } catch (FW_Cache_Not_Found_Exception $e) {
26
+ FW_Cache::set(
27
+ $cache_key,
28
+ $dir = apply_filters('fw_framework_customizations_dir_rel_path', '/framework-customizations')
29
+ );
30
+ }
31
+
32
+ return $dir . $append;
33
+ }
34
+
35
+ /** Child theme related functions */
36
+ {
37
+ /**
38
+ * Full path to the child-theme framework customizations directory
39
+ * @param string $rel_path
40
+ * @return null|string
41
+ */
42
+ function fw_get_stylesheet_customizations_directory($rel_path = '') {
43
+ if (is_child_theme()) {
44
+ return get_stylesheet_directory() . fw_get_framework_customizations_dir_rel_path($rel_path);
45
+ } else {
46
+ // check is_child_theme() before using this function
47
+ return null;
48
+ }
49
+ }
50
+
51
+ /**
52
+ * URI to the child-theme framework customizations directory
53
+ * @param string $rel_path
54
+ * @return null|string
55
+ */
56
+ function fw_get_stylesheet_customizations_directory_uri($rel_path = '') {
57
+ if (is_child_theme()) {
58
+ return get_stylesheet_directory_uri() . fw_get_framework_customizations_dir_rel_path($rel_path);
59
+ } else {
60
+ // check is_child_theme() before using this function
61
+ return null;
62
+ }
63
+ }
64
+ }
65
+
66
+ /** Parent theme related functions */
67
+ {
68
+ /**
69
+ * Full path to the parent-theme framework customizations directory
70
+ * @param string $rel_path
71
+ * @return string
72
+ */
73
+ function fw_get_template_customizations_directory($rel_path = '') {
74
+ try {
75
+ $dir = FW_Cache::get($cache_key = 'fw_template_customizations_dir');
76
+ } catch (FW_Cache_Not_Found_Exception $e) {
77
+ FW_Cache::set(
78
+ $cache_key,
79
+ $dir = get_template_directory() . fw_get_framework_customizations_dir_rel_path()
80
+ );
81
+ }
82
+
83
+ return $dir . $rel_path;
84
+ }
85
+
86
+ /**
87
+ * URI to the parent-theme framework customizations directory
88
+ * @param string $rel_path
89
+ * @return string
90
+ */
91
+ function fw_get_template_customizations_directory_uri($rel_path = '') {
92
+ try {
93
+ $dir = FW_Cache::get($cache_key = 'fw_template_customizations_dir_uri');
94
+ } catch (FW_Cache_Not_Found_Exception $e) {
95
+ FW_Cache::set(
96
+ $cache_key,
97
+ $dir = get_template_directory_uri() . fw_get_framework_customizations_dir_rel_path()
98
+ );
99
+ }
100
+
101
+ return $dir . $rel_path;
102
+ }
103
+ }
104
+
105
+ /** Framework related functions */
106
+ {
107
+ /**
108
+ * Full path to the parent-theme/framework directory
109
+ * @param string $rel_path
110
+ * @return string
111
+ */
112
+ function fw_get_framework_directory($rel_path = '') {
113
+ try {
114
+ $dir = FW_Cache::get($cache_key = 'fw_framework_dir');
115
+ } catch (FW_Cache_Not_Found_Exception $e) {
116
+ FW_Cache::set(
117
+ $cache_key,
118
+ $dir = apply_filters(
119
+ 'fw_framework_directory',
120
+ fw_fix_path(dirname(dirname(__FILE__))) // double dirname() to remove '/helpers', use parent dir
121
+ )
122
+ );
123
+ }
124
+
125
+ return $dir . $rel_path;
126
+ }
127
+
128
+ /**
129
+ * URI to the parent-theme/framework directory
130
+ * @param string $rel_path
131
+ * @return string
132
+ */
133
+ function fw_get_framework_directory_uri($rel_path = '') {
134
+ try {
135
+ $uri = FW_Cache::get($cache_key = 'fw_framework_dir_uri');
136
+ } catch (FW_Cache_Not_Found_Exception $e) {
137
+ FW_Cache::set(
138
+ $cache_key,
139
+ $uri = apply_filters(
140
+ 'fw_framework_directory_uri',
141
+ ($uri = fw_get_path_url(fw_get_framework_directory()))
142
+ ? $uri
143
+ : get_template_directory_uri() . '/framework'
144
+ )
145
+ );
146
+ }
147
+
148
+ return $uri . $rel_path;
149
+ }
150
+ }
151
+
152
  /**
153
  * Recursively find a key's value in array
154
  *
635
  * @return string URI
636
  */
637
  function fw_locate_theme_path_uri($rel_path) {
638
+ if (is_child_theme() && file_exists(get_stylesheet_directory() . $rel_path)) {
639
+ return get_stylesheet_directory_uri() . $rel_path;
640
+ } elseif (file_exists(get_template_directory() . $rel_path)) {
641
+ return get_template_directory_uri() . $rel_path;
642
+ } else {
643
+ return 'about:blank#theme-file-not-found:'. $rel_path;
 
 
 
 
 
 
 
 
644
  }
645
  }
646
 
651
  * @return string URI
652
  */
653
  function fw_locate_theme_path($rel_path) {
654
+ if (is_child_theme() && file_exists(get_stylesheet_directory() . $rel_path)) {
655
+ return get_stylesheet_directory() . $rel_path;
656
+ } elseif (file_exists(get_template_directory() . $rel_path)) {
657
+ return get_template_directory() . $rel_path;
658
+ } else {
659
+ return false;
 
 
 
 
 
 
 
 
660
  }
661
  }
662
 
1479
  if (!empty($args['width']) and !empty($args['height']) and class_exists('DOMDocument') and !empty($html)) {
1480
  $dom_element = new DOMDocument();
1481
  @$dom_element->loadHTML($html);
1482
+
1483
+ if ($obj = $dom_element->getElementsByTagName('iframe')->item(0)) {
1484
+ $obj->setAttribute('width', $args['width']);
1485
+ $obj->setAttribute('height', $args['height']);
1486
+ //saveXml instead of SaveHTML for php version compatibility
1487
+ $html = $dom_element->saveXML($obj, LIBXML_NOEMPTYTAG);
1488
+ }
1489
  }
1490
 
1491
  return $html;
1501
  * http://www.zimuel.it/en/strong-cryptography-in-php/
1502
  * > Don't use rand() or mt_rand()
1503
  */
1504
+ function fw_secure_rand($length) {
 
1505
  if (function_exists('openssl_random_pseudo_bytes')) {
1506
  $rnd = openssl_random_pseudo_bytes($length, $strong);
1507
  if ($strong) {
1643
  * @return array|bool
1644
  */
1645
  function fw_get_image_sizes( $size = '' ) {
 
1646
  global $_wp_additional_image_sizes;
1647
 
1648
  $sizes = array();
1650
 
1651
  // Create the full array with sizes and crop info
1652
  foreach( $get_intermediate_image_sizes as $_size ) {
 
1653
  if ( in_array( $_size, array( 'thumbnail', 'medium', 'large' ) ) ) {
 
1654
  $sizes[ $_size ]['width'] = get_option( $_size . '_size_w' );
1655
  $sizes[ $_size ]['height'] = get_option( $_size . '_size_h' );
1656
  $sizes[ $_size ]['crop'] = (bool) get_option( $_size . '_crop' );
 
1657
  } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
 
1658
  $sizes[ $_size ] = array(
1659
  'width' => $_wp_additional_image_sizes[ $_size ]['width'],
1660
  'height' => $_wp_additional_image_sizes[ $_size ]['height'],
1661
  'crop' => $_wp_additional_image_sizes[ $_size ]['crop']
1662
  );
 
1663
  }
 
1664
  }
1665
 
1666
  // Get only 1 size if found
1667
  if ( $size ) {
 
1668
  if( isset( $sizes[ $size ] ) ) {
1669
  return $sizes[ $size ];
1670
  } else {
1671
  return false;
1672
  }
 
1673
  }
1674
 
1675
  return $sizes;
1799
  return ( ! is_wp_error( $response ) && ! empty( $response['src'] ) ) ? $response['src'] : $url;
1800
  }
1801
  }
1802
+
1803
+ /**
1804
+ * fw_get_path_url( dirname(__FILE__) .'/test.css' ) --> http://site.url/path/to/test.css
1805
+ * @param string $path
1806
+ * @return string|null
1807
+ * @since 2.6.11
1808
+ */
1809
+ function fw_get_path_url($path) {
1810
+ try {
1811
+ $paths_to_urls = FW_Cache::get($cache_key = 'fw:paths_to_urls');
1812
+ } catch (FW_Cache_Not_Found_Exception $e) {
1813
+ $wp_upload_dir = wp_upload_dir();
1814
+
1815
+ $paths_to_urls = array(
1816
+ fw_fix_path(WP_PLUGIN_DIR) => plugins_url(),
1817
+ fw_fix_path(get_theme_root()) => get_theme_root_uri(),
1818
+ fw_fix_path($wp_upload_dir['basedir']) => $wp_upload_dir['baseurl'],
1819
+ );
1820
+
1821
+ if (is_multisite() && WPMU_PLUGIN_DIR) {
1822
+ $paths_to_urls[ fw_fix_path(WPMU_PLUGIN_DIR) ] = WPMU_PLUGIN_URL;
1823
+ }
1824
+
1825
+ FW_Cache::set($cache_key, $paths_to_urls);
1826
+ }
1827
+
1828
+ $path = fw_fix_path($path);
1829
+
1830
+ foreach ($paths_to_urls as $_path => $_url) {
1831
+ if (preg_match($regex = '/^'. preg_quote($_path, '/') .'($|\/)/', $path)) {
1832
+ return $_url .'/'. preg_replace($regex, '', $path);
1833
+ }
1834
+ }
1835
+
1836
+ return null;
1837
+ }
framework/includes/container-types/box/class-fw-container-type-box.php CHANGED
@@ -45,4 +45,3 @@ class FW_Container_Type_Box extends FW_Container_Type {
45
  return $html;
46
  }
47
  }
48
- FW_Container_Type::register('FW_Container_Type_Box');
45
  return $html;
46
  }
47
  }
 
framework/includes/container-types/popup/class-fw-container-type-popup.php CHANGED
@@ -74,4 +74,3 @@ class FW_Container_Type_Popup extends FW_Container_Type {
74
  return $html;
75
  }
76
  }
77
- FW_Container_Type::register('FW_Container_Type_Popup');
74
  return $html;
75
  }
76
  }
 
framework/includes/container-types/simple.php CHANGED
@@ -38,4 +38,3 @@ class FW_Container_Type_Group extends FW_Container_Type {
38
  return $html;
39
  }
40
  }
41
- FW_Container_Type::register('FW_Container_Type_Group');
38
  return $html;
39
  }
40
  }
 
framework/includes/container-types/tab/class-fw-container-type-tab.php CHANGED
@@ -26,4 +26,3 @@ class FW_Container_Type_Tab extends FW_Container_Type {
26
  );
27
  }
28
  }
29
- FW_Container_Type::register('FW_Container_Type_Tab');
26
  );
27
  }
28
  }
 
framework/includes/customizer/class--fw-customizer-control-option-wrapper.php CHANGED
@@ -10,9 +10,7 @@ class _FW_Customizer_Control_Option_Wrapper extends WP_Customize_Control {
10
  <?php
11
  echo fw()->backend->render_options(
12
  array($this->id => $this->setting->get_fw_option()),
13
- array(
14
- $this->id => $this->value()
15
- ),
16
  array(),
17
  'customizer'
18
  );
10
  <?php
11
  echo fw()->backend->render_options(
12
  array($this->id => $this->setting->get_fw_option()),
13
+ array($this->id => $this->value()),
 
 
14
  array(),
15
  'customizer'
16
  );
framework/includes/customizer/class--fw-customizer-setting-option.php CHANGED
@@ -7,6 +7,12 @@ class _FW_Customizer_Setting_Option extends WP_Customize_Setting {
7
  */
8
  protected $fw_option = array();
9
 
 
 
 
 
 
 
10
  public function get_fw_option() {
11
  return $this->fw_option;
12
  }
@@ -35,4 +41,30 @@ class _FW_Customizer_Setting_Option extends WP_Customize_Setting {
35
 
36
  return $value;
37
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  }
7
  */
8
  protected $fw_option = array();
9
 
10
+ /**
11
+ * @var string
12
+ * This is sent in args and set in parent construct
13
+ */
14
+ protected $fw_option_id;
15
+
16
  public function get_fw_option() {
17
  return $this->fw_option;
18
  }
41
 
42
  return $value;
43
  }
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function value() {
49
+ return fw_db_option_storage_load(
50
+ $this->fw_option_id,
51
+ $this->fw_option,
52
+ parent::value(),
53
+ array('customizer' => true)
54
+ );
55
+ }
56
+
57
+ /**
58
+ * {@inheritdoc}
59
+ */
60
+ protected function update( $value ) {
61
+ return parent::update(
62
+ fw_db_option_storage_save(
63
+ $this->fw_option_id,
64
+ $this->fw_option,
65
+ $value,
66
+ array('customizer' => true)
67
+ )
68
+ );
69
+ }
70
  }
framework/includes/hooks.php CHANGED
@@ -1,4 +1,6 @@
1
- <?php if (!defined('FW')) die('Forbidden');
 
 
2
  /**
3
  * Filters and Actions
4
  */
@@ -11,51 +13,110 @@
11
  * @internal
12
  */
13
  function _action_fw_init_option_types() {
14
- require_once dirname(__FILE__) .'/option-types/init.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  }
16
- add_action('fw_option_types_init', '_action_fw_init_option_types');
 
17
 
18
  /**
19
  * Some option-types have add_action('wp_ajax_...')
20
  * so init all option-types if current request is ajax
21
  * @since 2.6.1
22
  */
23
- if (defined('DOING_AJAX') && DOING_AJAX) {
24
  function _action_fw_init_option_types_on_ajax() {
25
- fw()->backend->option_type('text');
 
 
26
  }
27
- add_action('fw_init', '_action_fw_init_option_types_on_ajax');
 
28
  }
29
 
30
  /**
31
  * Prevent Fatal Error if someone is registering option-types in old way (right away)
32
  * not in 'fw_option_types_init' action
 
33
  * @param string $class
34
  */
35
- function _fw_autoload_option_types($class) {
36
- if ('FW_Option_Type' === $class) {
37
- require_once dirname(__FILE__) .'/../core/extends/class-fw-option-type.php';
38
-
39
- if (is_admin() && defined('WP_DEBUG') && WP_DEBUG) {
40
  FW_Flash_Messages::add(
41
  'option-type-register-wrong',
42
- __("Please register option-types on 'fw_option_types_init' action", 'fw'),
43
  'warning'
44
  );
45
  }
46
- } elseif ('FW_Container_Type' === $class) {
47
- require_once dirname(__FILE__) .'/../core/extends/class-fw-container-type.php';
48
-
49
- if (is_admin() && defined('WP_DEBUG') && WP_DEBUG) {
50
  FW_Flash_Messages::add(
51
  'container-type-register-wrong',
52
- __("Please register container-types on 'fw_container_types_init' action", 'fw'),
53
  'warning'
54
  );
55
  }
56
  }
57
  }
58
- spl_autoload_register('_fw_autoload_option_types');
 
59
  }
60
 
61
  /**
@@ -66,9 +127,13 @@
66
  * @internal
67
  */
68
  function _action_fw_init_container_types() {
69
- require_once dirname(__FILE__) .'/container-types/init.php';
 
 
 
70
  }
71
- add_action('fw_container_types_init', '_action_fw_init_container_types');
 
72
  }
73
 
74
  /**
@@ -78,32 +143,37 @@
78
  * https://github.com/ThemeFuse/Unyson/issues/138
79
  * @internal
80
  */
81
- function _fw_filter_github_api_url($url) {
82
  return 'http://github-api-cache.unyson.io';
83
  }
84
- add_filter('fw_github_api_url', '_fw_filter_github_api_url');
 
85
 
86
  /**
87
  * Javascript events related to tinymce init
88
  * @since 2.6.0
89
  */
90
  {
91
- add_action('wp_tiny_mce_init', '_fw_action_tiny_mce_init');
92
- function _fw_action_tiny_mce_init($mce_settings) {
93
- ?>
94
- <script type="text/javascript">
95
- if (typeof fwEvents != 'undefined') { fwEvents.trigger('fw:tinymce:init:before'); }
96
- </script>
97
- <?php
 
 
98
  }
99
 
100
- add_action('after_wp_tiny_mce', '_fw_action_after_wp_tiny_mce');
101
- function _fw_action_after_wp_tiny_mce($mce_settings) {
102
- ?>
103
- <script type="text/javascript">
104
- if (typeof fwEvents != 'undefined') { fwEvents.trigger('fw:tinymce:init:after'); }
105
- </script>
106
- <?php
 
 
107
  }
108
  }
109
 
@@ -125,6 +195,7 @@ add_filter('fw_github_api_url', '_fw_filter_github_api_url');
125
  FW_Flash_Messages::add( 'fw-form-admin-' . $input_name, $error_message, 'error' );
126
  }
127
  }
 
128
  add_action( 'wp_loaded', '_action_fw_form_show_errors_in_admin', 111 );
129
  } else {
130
  /**
@@ -140,23 +211,25 @@ add_filter('fw_github_api_url', '_fw_filter_github_api_url');
140
 
141
  echo '<style type="text/css">.fw-form-errors { color: #bf0000; }</style>';
142
  }
 
143
  add_action( 'wp_print_styles', '_action_fw_form_frontend_default_styles' );
144
  }
145
  }
146
 
147
  // FW_Flash_Messages hooks
148
  {
149
- if (is_admin()) {
150
  /**
151
  * Start the session before the content is sent to prevent the "headers already sent" warning
152
  * @internal
153
  */
154
  function _action_fw_flash_message_backend_prepare() {
155
- if (!session_id()) {
156
  session_start();
157
  }
158
  }
159
- add_action('current_screen', '_action_fw_flash_message_backend_prepare', 9999);
 
160
 
161
  /**
162
  * Display flash messages in backend as notices
@@ -176,35 +249,36 @@ add_filter('fw_github_api_url', '_fw_filter_github_api_url');
176
  * each creating a new independent request that don't remember/use session cookie from previous request,
177
  * thus on server side are created many (not used) new sessions.
178
  */
179
- !(defined('DOING_AJAX') && DOING_AJAX)
180
  &&
181
- !session_id()
182
  ) {
183
  session_start();
184
  }
185
  }
186
- add_action('send_headers', '_action_fw_flash_message_frontend_prepare', 9999);
 
187
 
188
  /**
189
  * Print flash messages in frontend if this has not been done from theme
190
  */
191
  function _action_fw_flash_message_frontend_print() {
192
- if (FW_Flash_Messages::_frontend_printed()) {
193
  return;
194
  }
195
 
196
- if (!FW_Flash_Messages::_print_frontend()) {
197
  return;
198
  }
199
 
200
  ?>
201
  <script type="text/javascript">
202
- (function(){
203
  if (typeof jQuery === "undefined") {
204
  return;
205
  }
206
 
207
- jQuery(function($){
208
  var $container;
209
 
210
  // Try to find the content element
@@ -243,14 +317,26 @@ add_filter('fw_github_api_url', '_fw_filter_github_api_url');
243
  })();
244
  </script>
245
  <style type="text/css">
246
- .fw-flash-messages .fw-flash-type-error { color: #f00; }
247
- .fw-flash-messages .fw-flash-type-warning { color: #f70; }
248
- .fw-flash-messages .fw-flash-type-success { color: #070; }
249
- .fw-flash-messages .fw-flash-type-info { color: #07f; }
 
 
 
 
 
 
 
 
 
 
 
250
  </style>
251
  <?php
252
  }
253
- add_action('wp_footer', '_action_fw_flash_message_frontend_print', 9999);
 
254
  }
255
  }
256
 
@@ -270,4 +356,4 @@ add_filter('fw_github_api_url', '_fw_filter_github_api_url');
270
 
271
  add_action( 'delete_attachment', 'fw_delete_resized_thumbnails' );
272
  }
273
- }
1
+ <?php if ( ! defined( 'FW' ) ) {
2
+ die( 'Forbidden' );
3
+ }
4
  /**
5
  * Filters and Actions
6
  */
13
  * @internal
14
  */
15
  function _action_fw_init_option_types() {
16
+ FW_Option_Type::register( 'FW_Option_Type_Hidden' );
17
+ FW_Option_Type::register( 'FW_Option_Type_Text' );
18
+ FW_Option_Type::register( 'FW_Option_Type_Short_Text' );
19
+ FW_Option_Type::register( 'FW_Option_Type_Password' );
20
+ FW_Option_Type::register( 'FW_Option_Type_Textarea' );
21
+ FW_Option_Type::register( 'FW_Option_Type_Html' );
22
+ FW_Option_Type::register( 'FW_Option_Type_Html_Fixed' );
23
+ FW_Option_Type::register( 'FW_Option_Type_Html_Full' );
24
+ FW_Option_Type::register( 'FW_Option_Type_Checkbox' );
25
+ FW_Option_Type::register( 'FW_Option_Type_Checkboxes' );
26
+ FW_Option_Type::register( 'FW_Option_Type_Radio' );
27
+ FW_Option_Type::register( 'FW_Option_Type_Select' );
28
+ FW_Option_Type::register( 'FW_Option_Type_Short_Select' );
29
+ FW_Option_Type::register( 'FW_Option_Type_Select_Multiple' );
30
+ FW_Option_Type::register( 'FW_Option_Type_Unique' );
31
+ FW_Option_Type::register( 'FW_Option_Type_GMap_Key' );
32
+ FW_Option_Type::register( 'FW_Option_Type_Addable_Box' );
33
+ FW_Option_Type::register( 'FW_Option_Type_Addable_Option' );
34
+ FW_Option_Type::register( 'FW_Option_Type_Addable_Popup' );
35
+ FW_Option_Type::register( 'FW_Option_Type_Addable_Popup_Full' );
36
+ FW_Option_Type::register( 'FW_Option_Type_Background_Image' );
37
+ FW_Option_Type::register( 'FW_Option_Type_Color_Picker' );
38
+ FW_Option_Type::register( 'FW_Option_Type_Date_Picker' );
39
+ FW_Option_Type::register( 'FW_Option_Type_Datetime_Picker' );
40
+ FW_Option_Type::register( 'FW_Option_Type_Datetime_Range' );
41
+ FW_Option_Type::register( 'FW_Option_Type_Gradient' );
42
+ FW_Option_Type::register( 'FW_Option_Type_Icon' );
43
+ FW_Option_Type::register( 'FW_Option_Type_Image_Picker' );
44
+ FW_Option_Type::register( 'FW_Option_Type_Map' );
45
+ FW_Option_Type::register( 'FW_Option_Type_Multi' );
46
+ FW_Option_Type::register( 'FW_Option_Type_Multi_Picker' );
47
+ FW_Option_Type::register( 'FW_Option_Type_Multi_Upload' );
48
+ FW_Option_Type::register( 'FW_Option_Type_Popup' );
49
+ FW_Option_Type::register( 'FW_Option_Type_Radio_Text' );
50
+ FW_Option_Type::register( 'FW_Option_Type_Range_Slider' );
51
+ FW_Option_Type::register( 'FW_Option_Type_Rgba_Color_Picker' );
52
+ FW_Option_Type::register( 'FW_Option_Type_Slider' );
53
+ FW_Option_Type::register( 'FW_Option_Type_Slider_Short' );
54
+ FW_Option_Type::register( 'FW_Option_Type_Switch' );
55
+ FW_Option_Type::register( 'FW_Option_Type_Typography' );
56
+ FW_Option_Type::register( 'FW_Option_Type_Typography_v2' );
57
+ FW_Option_Type::register( 'FW_Option_Type_Upload' );
58
+ FW_Option_Type::register( 'FW_Option_Type_Wp_Editor' );
59
+
60
+ {
61
+ $favorites = new FW_Icon_V2_Favorites_Manager();
62
+ $favorites->attach_ajax_actions();
63
+
64
+ FW_Option_Type::register( 'FW_Option_Type_Icon_v2' );
65
+ }
66
+
67
+ {
68
+ FW_Option_Type::register( 'FW_Option_Type_Multi_Select' );
69
+ }
70
+
71
+ {
72
+ FW_Option_Type::register( 'FW_Option_Type_Oembed' );
73
+ }
74
  }
75
+
76
+ add_action( 'fw_option_types_init', '_action_fw_init_option_types' );
77
 
78
  /**
79
  * Some option-types have add_action('wp_ajax_...')
80
  * so init all option-types if current request is ajax
81
  * @since 2.6.1
82
  */
83
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
84
  function _action_fw_init_option_types_on_ajax() {
85
+ foreach (fw()->backend->get_option_types() as $type) {
86
+ fw()->backend->option_type($type);
87
+ }
88
  }
89
+
90
+ add_action( 'fw_init', '_action_fw_init_option_types_on_ajax' );
91
  }
92
 
93
  /**
94
  * Prevent Fatal Error if someone is registering option-types in old way (right away)
95
  * not in 'fw_option_types_init' action
96
+ *
97
  * @param string $class
98
  */
99
+ function _fw_autoload_option_types( $class ) {
100
+ if ( 'FW_Option_Type' === $class ) {
101
+ if ( is_admin() && defined( 'WP_DEBUG' ) && WP_DEBUG ) {
 
 
102
  FW_Flash_Messages::add(
103
  'option-type-register-wrong',
104
+ __( "Please register option-types on 'fw_option_types_init' action", 'fw' ),
105
  'warning'
106
  );
107
  }
108
+ } elseif ( 'FW_Container_Type' === $class ) {
109
+ if ( is_admin() && defined( 'WP_DEBUG' ) && WP_DEBUG ) {
 
 
110
  FW_Flash_Messages::add(
111
  'container-type-register-wrong',
112
+ __( "Please register container-types on 'fw_container_types_init' action", 'fw' ),
113
  'warning'
114
  );
115
  }
116
  }
117
  }
118
+
119
+ spl_autoload_register( '_fw_autoload_option_types' );
120
  }
121
 
122
  /**
127
  * @internal
128
  */
129
  function _action_fw_init_container_types() {
130
+ FW_Container_Type::register( 'FW_Container_Type_Group' );
131
+ FW_Container_Type::register( 'FW_Container_Type_Box' );
132
+ FW_Container_Type::register( 'FW_Container_Type_Popup' );
133
+ FW_Container_Type::register( 'FW_Container_Type_Tab' );
134
  }
135
+
136
+ add_action( 'fw_container_types_init', '_action_fw_init_container_types' );
137
  }
138
 
139
  /**
143
  * https://github.com/ThemeFuse/Unyson/issues/138
144
  * @internal
145
  */
146
+ function _fw_filter_github_api_url( $url ) {
147
  return 'http://github-api-cache.unyson.io';
148
  }
149
+
150
+ add_filter( 'fw_github_api_url', '_fw_filter_github_api_url' );
151
 
152
  /**
153
  * Javascript events related to tinymce init
154
  * @since 2.6.0
155
  */
156
  {
157
+ add_action( 'wp_tiny_mce_init', '_fw_action_tiny_mce_init' );
158
+ function _fw_action_tiny_mce_init( $mce_settings ) {
159
+ ?>
160
+ <script type="text/javascript">
161
+ if (typeof fwEvents != 'undefined') {
162
+ fwEvents.trigger('fw:tinymce:init:before');
163
+ }
164
+ </script>
165
+ <?php
166
  }
167
 
168
+ add_action( 'after_wp_tiny_mce', '_fw_action_after_wp_tiny_mce' );
169
+ function _fw_action_after_wp_tiny_mce( $mce_settings ) {
170
+ ?>
171
+ <script type="text/javascript">
172
+ if (typeof fwEvents != 'undefined') {
173
+ fwEvents.trigger('fw:tinymce:init:after');
174
+ }
175
+ </script>
176
+ <?php
177
  }
178
  }
179
 
195
  FW_Flash_Messages::add( 'fw-form-admin-' . $input_name, $error_message, 'error' );
196
  }
197
  }
198
+
199
  add_action( 'wp_loaded', '_action_fw_form_show_errors_in_admin', 111 );
200
  } else {
201
  /**
211
 
212
  echo '<style type="text/css">.fw-form-errors { color: #bf0000; }</style>';
213
  }
214
+
215
  add_action( 'wp_print_styles', '_action_fw_form_frontend_default_styles' );
216
  }
217
  }
218
 
219
  // FW_Flash_Messages hooks
220
  {
221
+ if ( is_admin() ) {
222
  /**
223
  * Start the session before the content is sent to prevent the "headers already sent" warning
224
  * @internal
225
  */
226
  function _action_fw_flash_message_backend_prepare() {
227
+ if ( ! session_id() ) {
228
  session_start();
229
  }
230
  }
231
+
232
+ add_action( 'current_screen', '_action_fw_flash_message_backend_prepare', 9999 );
233
 
234
  /**
235
  * Display flash messages in backend as notices
249
  * each creating a new independent request that don't remember/use session cookie from previous request,
250
  * thus on server side are created many (not used) new sessions.
251
  */
252
+ ! ( defined( 'DOING_AJAX' ) && DOING_AJAX )
253
  &&
254
+ ! session_id()
255
  ) {
256
  session_start();
257
  }
258
  }
259
+
260
+ add_action( 'send_headers', '_action_fw_flash_message_frontend_prepare', 9999 );
261
 
262
  /**
263
  * Print flash messages in frontend if this has not been done from theme
264
  */
265
  function _action_fw_flash_message_frontend_print() {
266
+ if ( FW_Flash_Messages::_frontend_printed() ) {
267
  return;
268
  }
269
 
270
+ if ( ! FW_Flash_Messages::_print_frontend() ) {
271
  return;
272
  }
273
 
274
  ?>
275
  <script type="text/javascript">
276
+ (function () {
277
  if (typeof jQuery === "undefined") {
278
  return;
279
  }
280
 
281
+ jQuery(function ($) {
282
  var $container;
283
 
284
  // Try to find the content element
317
  })();
318
  </script>
319
  <style type="text/css">
320
+ .fw-flash-messages .fw-flash-type-error {
321
+ color: #f00;
322
+ }
323
+
324
+ .fw-flash-messages .fw-flash-type-warning {
325
+ color: #f70;
326
+ }
327
+
328
+ .fw-flash-messages .fw-flash-type-success {
329
+ color: #070;
330
+ }
331
+
332
+ .fw-flash-messages .fw-flash-type-info {
333
+ color: #07f;
334
+ }
335
  </style>
336
  <?php
337
  }
338
+
339
+ add_action( 'wp_footer', '_action_fw_flash_message_frontend_print', 9999 );
340
  }
341
  }
342
 
356
 
357
  add_action( 'delete_attachment', 'fw_delete_resized_thumbnails' );
358
  }
359
+ }
framework/includes/option-storage/type/class-fw-option-storage-type-term-meta.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if (!defined('FW')) die('Forbidden');
2
+
3
+ /**
4
+ * array(
5
+ * 'term-id' => 3 // optional // hardcoded term id
6
+ * 'term-meta' => 'hello_world' // optional (default: 'fw:opt:{option_id}')
7
+ * 'key' => 'option_id/sub_key' // optional
8
+ * )
9
+ */
10
+ class FW_Option_Storage_Type_Term_Meta extends FW_Option_Storage_Type {
11
+ public function get_type() {
12
+ return 'term-meta';
13
+ }
14
+
15
+ /**
16
+ * {@inheritdoc}
17
+ */
18
+ protected function _save( $id, array $option, $value, array $params ) {
19
+ if ($term_id = $this->get_term_id($option, $params)) {
20
+ $meta_id = $this->get_meta_id($id, $option, $params);
21
+
22
+ if (isset($option['fw-storage']['key'])) {
23
+ $meta_value = get_term_meta($term_id, $meta_id, true);
24
+
25
+ fw_aks($option['fw-storage']['key'], $value, $meta_value);
26
+
27
+ update_term_meta($term_id, $meta_id, $meta_value);
28
+
29
+ unset($meta_value);
30
+ } else {
31
+ update_term_meta($term_id, $meta_id, $value);
32
+ }
33
+
34
+ return fw()->backend->option_type($option['type'])->get_value_from_input(
35
+ array('type' => $option['type']), null
36
+ );
37
+ } else {
38
+ return $value;
39
+ }
40
+ }
41
+
42
+ /**
43
+ * {@inheritdoc}
44
+ */
45
+ protected function _load( $id, array $option, $value, array $params ) {
46
+ if ($term_id = $this->get_term_id($option, $params)) {
47
+ $meta_id = $this->get_meta_id($id, $option, $params);
48
+ $meta_value = get_term_meta($term_id, $meta_id, true);
49
+
50
+ if ($meta_value === '' && is_array($value)) {
51
+ return $value;
52
+ }
53
+
54
+ if (isset($option['fw-storage']['key'])) {
55
+ return fw_akg($option['fw-storage']['key'], $meta_value, $value);
56
+ } else {
57
+ return $meta_value;
58
+ }
59
+ } else {
60
+ return $value;
61
+ }
62
+ }
63
+
64
+ private function get_term_id($option, $params) {
65
+ $term_id = null;
66
+
67
+ if (!empty($option['fw-storage']['term-id'])) {
68
+ $term_id = $option['fw-storage']['term-id'];
69
+ } elseif (!empty($params['term-id'])) {
70
+ $term_id = $params['term-id'];
71
+ }
72
+
73
+ $term_id = intval($term_id);
74
+
75
+ if ($term_id > 0) {
76
+ return $term_id;
77
+ } else {
78
+ return false;
79
+ }
80
+ }
81
+
82
+ private function get_meta_id($id, $option, $params) {
83
+ return empty($option['fw-storage']['term-meta'])
84
+ ? 'fw:opt:'. $id
85
+ : $option['fw-storage']['term-meta'];
86
+ }
87
+ }
framework/includes/option-types/addable-box/class-fw-option-type-addable-box.php CHANGED
@@ -216,4 +216,3 @@ class FW_Option_Type_Addable_Box extends FW_Option_Type
216
  return 'auto';
217
  }
218
  }
219
- FW_Option_Type::register('FW_Option_Type_Addable_Box');
216
  return 'auto';
217
  }
218
  }
 
framework/includes/option-types/addable-option/class-fw-option-type-addable-option.php CHANGED
@@ -96,4 +96,3 @@ class FW_Option_Type_Addable_Option extends FW_Option_Type
96
  return $value;
97
  }
98
  }
99
- FW_Option_Type::register('FW_Option_Type_Addable_Option');
96
  return $value;
97
  }
98
  }
 
framework/includes/option-types/addable-popup/class-fw-option-type-addable-popup.php CHANGED
@@ -193,8 +193,6 @@ class FW_Option_Type_Addable_Popup extends FW_Option_Type
193
 
194
  }
195
 
196
- FW_Option_Type::register('FW_Option_Type_Addable_Popup');
197
-
198
  class FW_Option_Type_Addable_Popup_Full extends FW_Option_Type_Addable_Popup
199
  {
200
  public function get_type()
@@ -214,6 +212,4 @@ class FW_Option_Type_Addable_Popup_Full extends FW_Option_Type_Addable_Popup
214
 
215
  return parent::_render($id, $option, $data);
216
  }
217
- }
218
-
219
- FW_Option_Type::register('FW_Option_Type_Addable_Popup_Full');
193
 
194
  }
195
 
 
 
196
  class FW_Option_Type_Addable_Popup_Full extends FW_Option_Type_Addable_Popup
197
  {
198
  public function get_type()
212
 
213
  return parent::_render($id, $option, $data);
214
  }
215
+ }
 
 
framework/includes/option-types/background-image/class-fw-option-type-background-image.php CHANGED
@@ -139,5 +139,3 @@ class FW_Option_Type_Background_Image extends FW_Option_Type {
139
  return $input_value;
140
  }
141
  }
142
-
143
- FW_Option_Type::register('FW_Option_Type_Background_Image');
139
  return $input_value;
140
  }
141
  }
 
 
framework/includes/option-types/color-picker/class-fw-option-type-color-picker.php CHANGED
@@ -106,4 +106,3 @@ class FW_Option_Type_Color_Picker extends FW_Option_Type
106
  );
107
  }
108
  }
109
- FW_Option_Type::register('FW_Option_Type_Color_Picker');
106
  );
107
  }
108
  }
 
framework/includes/option-types/date-picker/class-fw-option-type-wp-date-picker.php CHANGED
@@ -120,6 +120,4 @@ class FW_Option_Type_Date_Picker extends FW_Option_Type {
120
 
121
  return (string)$input_value;
122
  }
123
- }
124
-
125
- FW_Option_Type::register('FW_Option_Type_Date_Picker');
120
 
121
  return (string)$input_value;
122
  }
123
+ }
 
 
framework/includes/option-types/datetime-picker/class-fw-option-type-datetime-picker.php CHANGED
@@ -153,5 +153,4 @@ class FW_Option_Type_Datetime_Picker extends FW_Option_Type {
153
  return false;
154
  }
155
 
156
- }
157
- FW_Option_Type::register('FW_Option_Type_Datetime_Picker');
153
  return false;
154
  }
155
 
156
+ }
 
framework/includes/option-types/datetime-range/class-fw-option-type-datetime-range.php CHANGED
@@ -114,5 +114,4 @@ class FW_Option_Type_Datetime_Range extends FW_Option_Type {
114
  }
115
 
116
 
117
- }
118
- FW_Option_Type::register('FW_Option_Type_Datetime_Range');
114
  }
115
 
116
 
117
+ }
 
framework/includes/option-types/gradient/class-fw-option-type-gradient.php CHANGED
@@ -89,6 +89,4 @@ class FW_Option_Type_Gradient extends FW_Option_Type
89
  )
90
  );
91
  }
92
- }
93
-
94
- FW_Option_Type::register('FW_Option_Type_Gradient');
89
  )
90
  );
91
  }
92
+ }
 
 
framework/includes/option-types/icon-v2/class-fw-option-type-icon-v2.php CHANGED
@@ -2,9 +2,6 @@
2
 
3
  if (! defined('FW')) { die('Forbidden'); }
4
 
5
- require_once dirname(__FILE__) . '/includes/class-fw-icon-v2-packs-loader.php';
6
- require_once dirname(__FILE__) . '/includes/class-fw-icon-v2-favorites.php';
7
-
8
  class FW_Option_Type_Icon_v2 extends FW_Option_Type
9
  {
10
  private $enqueued_font_styles = array();
@@ -197,8 +194,3 @@ class FW_Option_Type_Icon_v2 extends FW_Option_Type
197
  return 'full';
198
  }
199
  }
200
-
201
- $favorites = new FW_Icon_V2_Favorites_Manager();
202
- $favorites->attach_ajax_actions();
203
-
204
- FW_Option_Type::register( 'FW_Option_Type_Icon_v2' );
2
 
3
  if (! defined('FW')) { die('Forbidden'); }
4
 
 
 
 
5
  class FW_Option_Type_Icon_v2 extends FW_Option_Type
6
  {
7
  private $enqueued_font_styles = array();
194
  return 'full';
195
  }
196
  }
 
 
 
 
 
framework/includes/option-types/icon-v2/includes/class-fw-icon-v2-packs-loader.php CHANGED
@@ -307,7 +307,7 @@ class FW_Icon_V2_Packs_Loader
307
  '/static/libs/font-awesome/css/font-awesome.min.css'
308
  ),
309
 
310
- 'admin_wp_enqueue_handle' => 'fw-font-awesome'
311
  ),
312
 
313
  'entypo' => array(
307
  '/static/libs/font-awesome/css/font-awesome.min.css'
308
  ),
309
 
310
+ 'admin_wp_enqueue_handle' => 'font-awesome'
311
  ),
312
 
313
  'entypo' => array(
framework/includes/option-types/icon/class-fw-option-type-icon.php CHANGED
@@ -935,5 +935,4 @@ class FW_Option_Type_Icon extends FW_Option_Type
935
  ),
936
  );
937
  }
938
- }
939
- FW_Option_Type::register('FW_Option_Type_Icon');
935
  ),
936
  );
937
  }
938
+ }
 
framework/includes/option-types/image-picker/class-fw-option-type-image-picker.php CHANGED
@@ -201,6 +201,4 @@ class Fw_Option_Type_Image_Picker extends FW_Option_Type
201
  {
202
  return 'auto';
203
  }
204
- }
205
-
206
- FW_Option_Type::register('FW_Option_Type_Image_Picker');
201
  {
202
  return 'auto';
203
  }
204
+ }
 
 
framework/includes/option-types/map/class-fw-option-type-map.php CHANGED
@@ -102,6 +102,4 @@ class FW_Option_Type_Map extends FW_Option_Type {
102
  public static function api_key() {
103
  return FW_Option_Type_GMap_Key::get_key();
104
  }
105
- }
106
-
107
- FW_Option_Type::register( 'FW_Option_Type_Map' );
102
  public static function api_key() {
103
  return FW_Option_Type_GMap_Key::get_key();
104
  }
105
+ }
 
 
framework/includes/option-types/multi-picker/class-fw-option-type-multi-picker.php CHANGED
@@ -214,6 +214,11 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
214
  E_USER_ERROR
215
  );
216
  }
 
 
 
 
 
217
 
218
  {
219
  reset($option['picker']);
@@ -283,6 +288,51 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
283
 
284
  return array_merge($picker_group, $choices_groups);
285
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
 
287
  /**
288
  * @internal
@@ -297,6 +347,11 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
297
  }
298
 
299
  $value = array();
 
 
 
 
 
300
 
301
  if (is_null($input_value) && isset($option['value'][$picker_key])) {
302
  $value[$picker_key] = $option['value'][$picker_key];
@@ -366,4 +421,3 @@ class FW_Option_Type_Multi_Picker extends FW_Option_Type
366
  return fw_db_option_storage_save($id, $option, $value, $params);
367
  }
368
  }
369
- FW_Option_Type::register('FW_Option_Type_Multi_Picker');
214
  E_USER_ERROR
215
  );
216
  }
217
+
218
+ /**
219
+ * @since 2.6.11
220
+ */
221
+ $option = $this->prepare_choices($option);
222
 
223
  {
224
  reset($option['picker']);
288
 
289
  return array_merge($picker_group, $choices_groups);
290
  }
291
+
292
+ /**
293
+ * Prepare `choices` array.
294
+ *
295
+ * @since 2.6.11
296
+ * @param array $option Options.
297
+ * @return array
298
+ */
299
+ protected function prepare_choices($option) {
300
+ $result = array();
301
+ $choices = fw_akg('choices', $option);
302
+
303
+ if (is_array($choices)) {
304
+ foreach ($choices as $key => $settings) {
305
+ if (isset($settings['for']) && isset($settings['options'])) {
306
+ if (is_array($settings['for'])) {
307
+ // Insert location: after/before.
308
+ $location = fw_akg('location', $settings, 'before');
309
+ foreach ($settings['for'] as $name) {
310
+ if (isset($choices[$name])) {
311
+ if ('before' === $location) {
312
+ $result[$name] = array_merge(
313
+ $settings['options'], $choices[$name]
314
+ );
315
+ } else {
316
+ $result[$name] = array_merge(
317
+ $choices[$name], $settings['options']
318
+ );
319
+ }
320
+ } else {
321
+ $result[$name] = $settings['options'];
322
+ }
323
+ }
324
+ }
325
+ } else {
326
+ if ( ! isset($result[$key]) ) {
327
+ $result[$key] = $settings;
328
+ }
329
+ }
330
+ }
331
+ }
332
+
333
+ fw_aks('choices', $result, $option);
334
+ return $option;
335
+ }
336
 
337
  /**
338
  * @internal
347
  }
348
 
349
  $value = array();
350
+
351
+ /**
352
+ * @since 2.6.11
353
+ */
354
+ $option = $this->prepare_choices($option);
355
 
356
  if (is_null($input_value) && isset($option['value'][$picker_key])) {
357
  $value[$picker_key] = $option['value'][$picker_key];
421
  return fw_db_option_storage_save($id, $option, $value, $params);
422
  }
423
  }
 
framework/includes/option-types/multi-select/class-fw-option-type-multi-select.php CHANGED
@@ -68,120 +68,180 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
68
  );
69
  }
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  /**
72
  * @internal
73
  */
74
- public static function _admin_action_get_ajax_response() {
75
- /**
76
- * @var WPDB $wpdb
77
- */
78
- global $wpdb;
79
 
80
  $type = FW_Request::POST( 'data/type' );
81
- $names = json_decode( FW_Request::POST( 'data/names' ), true );
82
  $title = FW_Request::POST( 'data/string' );
83
 
84
  $items = array();
85
 
86
  switch ( $type ) {
87
  case 'posts':
88
- $items = $wpdb->get_results(
89
- call_user_func_array(
90
- array( $wpdb, 'prepare' ),
91
- array_merge(
92
- array(
93
- "SELECT ID val, post_title title " .
94
- "FROM $wpdb->posts " .
95
- "WHERE post_title LIKE %s " .
96
- "AND post_status IN ( 'publish', 'private' ) " .
97
- //"AND NULLIF(post_password, '') IS NULL " . todo: review
98
- "AND post_type IN ( " .
99
- implode( ', ', array_fill( 1, count( $names ), '%s' ) ) .
100
- " ) " .
101
- "LIMIT 100",
102
- '%' . $wpdb->esc_like( $title ) . '%'
103
- ),
104
- /**
105
- * These strings may contain '%abc'
106
- * so we cannot use them directly in sql
107
- * because $wpdb->prepare() will return false
108
- * also you can test that with sprintf()
109
- */
110
- $names
111
- )
112
- )
113
- );
114
  break;
115
  case 'taxonomy':
116
- $items = $wpdb->get_results(
117
- call_user_func_array(
118
- array( $wpdb, 'prepare' ),
119
- array_merge(
120
- array(
121
- "SELECT terms.term_id val, terms.name title " .
122
- "FROM $wpdb->terms as terms, $wpdb->term_taxonomy as taxonomies " .
123
- "WHERE terms.name LIKE %s AND taxonomies.taxonomy IN ( " .
124
- implode( ', ', array_fill( 1, count( $names ), '%s' ) ) .
125
- " ) " .
126
- "AND terms.term_id = taxonomies.term_id " .
127
- "AND taxonomies.term_id = taxonomies.term_taxonomy_id " .
128
- "LIMIT 100",
129
- '%' . $wpdb->esc_like( $title ) . '%'
130
- ),
131
- /**
132
- * These strings may contain '%abc'
133
- * so we cannot use them directly in sql
134
- * because $wpdb->prepare() will return false
135
- * also you can test that with sprintf()
136
- */
137
- $names
138
- )
139
- )
140
- );
141
  break;
142
  case 'users':
143
- if ( empty( $names ) ) {
144
- $items = $wpdb->get_results(
145
- $wpdb->prepare(
146
- "SELECT users.id val, users.user_nicename title " .
147
- "FROM $wpdb->users as users " .
148
- "WHERE users.user_nicename LIKE %s " .
149
- "LIMIT 100",
150
- '%' . $wpdb->esc_like( $title ) . '%'
151
- )
152
- );
153
- } else {
154
- $like_user_meta = array();
155
- foreach ( $names as $name ) {
156
- $like_user_meta[] = '%' . $wpdb->esc_like( $name ) . '%';
157
- }
158
-
159
- $items = $wpdb->get_results(
160
- call_user_func_array(
161
- array( $wpdb, 'prepare' ),
162
- array_merge(
163
- array(
164
- "SELECT users.id val, users.user_nicename title " .
165
- "FROM $wpdb->users as users, $wpdb->usermeta as usermeta " .
166
- "WHERE users.user_nicename LIKE %s AND usermeta.meta_key = 'wp_capabilities' " .
167
- "AND ( " .
168
- implode( ' OR ',
169
- array_fill( 1, count( $like_user_meta ), 'usermeta.meta_value LIKE %s' ) ) .
170
- " ) " .
171
- "AND usermeta.user_id = users.ID",
172
- '%' . $wpdb->esc_like( $title ) . '%'
173
- ),
174
- /**
175
- * These strings may contain '%abc'
176
- * so we cannot use them directly in sql
177
- * because $wpdb->prepare() will return false
178
- * also you can test that with sprintf()
179
- */
180
- $like_user_meta
181
- )
182
- )
183
- );
184
- }
185
  break;
186
  }
187
 
@@ -199,233 +259,67 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
199
  * @internal
200
  */
201
  protected function _render( $id, $option, $data ) {
202
- $items = '';
203
- $population = 'array';
204
  $source = array();
 
205
 
206
  if ( isset( $option['population'] ) ) {
207
  switch ( $option['population'] ) {
208
  case 'array' :
209
  if ( isset( $option['choices'] ) && is_array( $option['choices'] ) ) {
210
- $items = $option['choices'];
 
 
 
 
 
211
  }
212
  break;
213
  case 'posts' :
214
  if ( isset( $option['source'] ) ) {
215
- /**
216
- * @var WPDB $wpdb
217
- */
218
- global $wpdb;
219
-
220
- $source = is_array( $option['source'] ) ? $option['source'] : array( $option['source'] );
221
- $population = 'posts';
222
-
223
- if ( isset( $option['prepopulate'] )
224
- && ( $number = (int) ( $option['prepopulate'] ) ) > 0
225
- && ! empty( $source )
226
- ) {
227
-
228
- $posts = $wpdb->get_results(
229
- "SELECT posts.ID, posts.post_title " .
230
- "FROM $wpdb->posts as posts " .
231
- "WHERE post_type IN ('" . implode( "', '", $source ) . "') " .
232
- "AND post_status IN ( 'publish', 'private' ) " .
233
- "ORDER BY post_date DESC LIMIT $number"
234
- );
235
-
236
- if ( ! empty( $posts ) || ! is_wp_error( $posts ) ) {
237
- $items = wp_list_pluck( $posts, 'post_title', 'ID' );
238
- }
239
- unset( $posts );
240
- }
241
-
242
- if ( empty( $data['value'] ) ) {
243
- break;
244
- }
245
-
246
- $ids = $data['value'];
247
- foreach ( $ids as $post_id ) {
248
- $ids[] = intval( $post_id );
249
- }
250
- $ids = implode( ', ', array_unique( $ids ) );
251
-
252
- $query = $wpdb->get_results(
253
- "SELECT posts.ID, posts.post_title " .
254
- "FROM $wpdb->posts as posts " .
255
- "WHERE posts.ID IN ( $ids )"
256
- );
257
-
258
- if ( is_wp_error( $query ) ) {
259
- break;
260
- }
261
-
262
- foreach ( $query as $post ) {
263
- $items[ $post->ID ] = $post->post_title;
264
- }
265
-
266
  }
267
  break;
268
  case 'taxonomy' :
269
  if ( isset( $option['source'] ) ) {
270
- /**
271
- * @var WPDB $wpdb
272
- */
273
- global $wpdb;
274
- $population = 'taxonomy';
275
- $source = is_array( $option['source'] ) ? $option['source'] : array( $option['source'] );
276
-
277
- if ( isset( $option['prepopulate'] ) && ! empty( $source )
278
- && ( $number = (int) ( $option['prepopulate'] ) ) > 0
279
- ) {
280
- $terms = $wpdb->get_results(
281
- "SELECT terms.term_id, terms.name " .
282
- "FROM $wpdb->terms as terms, $wpdb->term_taxonomy as taxonomies " .
283
- "WHERE taxonomies.taxonomy IN ('" . implode( "', '", $source ) . "') " .
284
- "AND terms.term_id = taxonomies.term_id " .
285
- "AND taxonomies.term_id = taxonomies.term_taxonomy_id"
286
- );
287
-
288
- if ( ! empty( $terms ) || ! is_wp_error( $terms ) ) {
289
- $items = wp_list_pluck( $terms, 'name', 'term_id' );
290
- }
291
- unset( $terms );
292
- }
293
-
294
- if ( empty( $data['value'] ) ) {
295
- break;
296
- }
297
-
298
- /**
299
- * @var WPDB $wpdb
300
- */
301
- global $wpdb;
302
-
303
- $ids = $data['value'];
304
- foreach ( $ids as $post_id ) {
305
- $ids[] = intval( $post_id );
306
- }
307
- $ids = implode( ', ', array_unique( $ids ) );
308
-
309
- $in_sources = array();
310
- foreach ( $source as $_source ) {
311
- $in_sources[] = $wpdb->prepare( '%s', $_source );
312
- }
313
- $in_sources = implode( ', ', $in_sources );
314
-
315
- $query = $wpdb->get_results(
316
- "SELECT terms.term_id id, terms.name title " .
317
- "FROM $wpdb->terms as terms, $wpdb->term_taxonomy as taxonomies " .
318
- "WHERE terms.term_id IN ( $ids ) AND taxonomies.taxonomy IN ( $in_sources ) " .
319
- "AND terms.term_id = taxonomies.term_id " .
320
- "AND taxonomies.term_id = taxonomies.term_taxonomy_id"
321
- );
322
-
323
- if ( is_wp_error( $query ) || empty( $query ) ) {
324
- break;
325
- }
326
-
327
- $items = array();
328
-
329
- foreach ( $query as $term ) {
330
- $items[ $term->id ] = $term->title;
331
- }
332
  }
333
  break;
334
  case 'users' :
335
- /**
336
- * @var WPDB $wpdb
337
- */
338
- global $wpdb;
339
- $population = 'users';
340
-
341
- if ( isset( $option['prepopulate'] )
342
- && ( $number = (int) ( $option['prepopulate'] ) ) > 0
343
- ) {
344
- $users = $wpdb->get_results(
345
- "SELECT DISTINCT users.ID, users.user_nicename " .
346
- "FROM $wpdb->users as users, $wpdb->usermeta usermeta " .
347
- ( ! empty( $source )
348
- ? "WHERE usermeta.meta_key = 'wp_capabilities'" .
349
- " AND usermeta.meta_value IN ('" . implode( "', ", $source ) . "')" .
350
- " AND usermeta.user_id = users.ID"
351
- : '' ) . " LIMIT $number"
352
- );
353
-
354
- if ( ! empty( $users ) || ! is_wp_error( $users ) ) {
355
- $items = wp_list_pluck( $users, 'user_nicename', 'ID' );
356
- }
357
- unset( $users );
358
- }
359
-
360
  if ( isset( $option['source'] ) && ! empty( $option['source'] ) ) {
361
  $source = is_array( $option['source'] ) ? $option['source'] : array( $option['source'] );
362
-
363
- if ( empty( $data['value'] ) ) {
364
- break;
365
- }
366
-
367
- $ids = $data['value'];
368
- foreach ( $ids as $post_id ) {
369
- $ids[] = intval( $post_id );
370
- }
371
- $ids = implode( ', ', array_unique( $ids ) );
372
-
373
- $in_sources = array();
374
- foreach ( $source as $_source ) {
375
- $in_sources[] = $wpdb->prepare( 'usermeta.meta_value LIKE %s',
376
- '%' . $wpdb->esc_like( $_source ) . '%' );
377
- }
378
- $in_sources = implode( ' OR ', $in_sources );
379
-
380
- $query = $wpdb->get_results(
381
- "SELECT users.id, users.user_nicename title " .
382
- "FROM $wpdb->users as users, $wpdb->usermeta usermeta " .
383
- "WHERE users.ID IN ($ids) AND usermeta.meta_key = 'wp_capabilities' AND ( $in_sources ) " .
384
- "AND usermeta.user_id = users.ID"
385
- );
386
-
387
  } else {
388
  $source = array();
389
-
390
- if ( empty( $data['value'] ) ) {
391
- break;
392
- }
393
-
394
- $ids = $data['value'];
395
- foreach ( $ids as $post_id ) {
396
- $ids[] = intval( $post_id );
397
- }
398
- $ids = implode( ', ', array_unique( $ids ) );
399
-
400
- $query = $wpdb->get_results(
401
- "SELECT users.id, users.user_nicename title " .
402
- "FROM $wpdb->users as users " .
403
- "WHERE users.ID IN ($ids)"
404
- );
405
- }
406
-
407
- if ( is_wp_error( $query ) || empty( $query ) ) {
408
- break;
409
- }
410
-
411
- $items = array();
412
-
413
- foreach ( $query as $term ) {
414
- $items[ $term->id ] = $term->title;
415
  }
416
 
 
 
 
 
 
417
  break;
418
  default :
419
- $items = '';
420
  }
421
 
422
- $option['attr']['data-options'] = json_encode( $this->convert_array( $items ) );
423
  $option['attr']['data-population'] = $population;
424
  $option['attr']['data-source'] = json_encode( $source );
425
  $option['attr']['data-limit'] = ( intval( $option['limit'] ) > 0 ) ? $option['limit'] : 0;
426
  } else {
427
- return '';
428
  }
 
429
  if ( ! empty( $data['value'] ) ) {
430
  $data['value'] = implode( '/*/', $data['value'] );
431
  } else {
@@ -457,25 +351,6 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
457
  fw()->backend->option_type( 'text' )->enqueue_static();
458
  }
459
 
460
- /**
461
- * @internal
462
- */
463
- private function convert_array( $array = array() ) {
464
- if ( ! is_array( $array ) || empty( $array ) ) {
465
- return array();
466
- }
467
-
468
- $return = array();
469
- foreach ( $array as $key => $item ) {
470
- $return[] = array(
471
- 'val' => $key,
472
- 'title' => ( $item ) ? $item : $key . ' (' . __( 'No title', 'fw' ) . ')',
473
- );
474
- }
475
-
476
- return $return;
477
- }
478
-
479
  /**
480
  * @internal
481
  */
@@ -490,9 +365,6 @@ if ( ! class_exists( 'FW_Option_Type_Multi_Select' ) ):
490
  }
491
  }
492
 
493
- FW_Option_Type::register( 'FW_Option_Type_Multi_Select' );
494
-
495
- add_action( 'wp_ajax_admin_action_get_ajax_response',
496
- array( "FW_Option_Type_Multi_Select", '_admin_action_get_ajax_response' ) );
497
-
498
  endif;
68
  );
69
  }
70
 
71
+ private static function query_posts(array $limits) {
72
+ $limits = array_merge(array(
73
+ 'type' => array(
74
+ 'post' => true,
75
+ 'page' => true,
76
+ ),
77
+ 'title' => '',
78
+ 'id' => array( /* 1, 7, 120 */ ),
79
+ 'limit' => 100,
80
+ ), $limits);
81
+
82
+ /** @var WPDB $wpdb */
83
+ global $wpdb;
84
+
85
+ $sql = "SELECT ID val, post_title title"
86
+ ." FROM $wpdb->posts"
87
+ ." WHERE post_status IN ( 'publish', 'private' )";
88
+ //." AND NULLIF(post_password, '') IS NULL"; todo: review
89
+
90
+ {
91
+ $prepare = array();
92
+
93
+ if ($limits['id']) {
94
+ $sql .= " AND ID IN ( "
95
+ . implode( ', ', array_fill( 1, count( $limits['id'] ), '%d' ) )
96
+ . " ) ";
97
+ $prepare = array_merge($prepare, $limits['id']);
98
+ }
99
+
100
+ if ($limits['type']) {
101
+ $sql .= " AND post_type IN ( "
102
+ . implode( ', ', array_fill( 1, count( $limits['type'] ), '%s' ) )
103
+ . " ) ";
104
+ $prepare = array_merge($prepare, array_keys($limits['type']));
105
+ }
106
+
107
+ if ($limits['title']) {
108
+ $sql .= " AND post_title LIKE %s";
109
+ $prepare[] = '%'. $wpdb->esc_like( $limits['title'] ) .'%';
110
+ }
111
+ }
112
+
113
+ $sql .= " LIMIT ". intval($limits['limit']);
114
+
115
+ return $wpdb->get_results($wpdb->prepare($sql, $prepare), ARRAY_A);
116
+ }
117
+
118
+ private static function query_terms(array $limits) {
119
+ $limits = array_merge(array(
120
+ 'taxonomy' => array(
121
+ 'category' => true,
122
+ ),
123
+ 'title' => '',
124
+ 'id' => array( /* 1, 7, 120 */ ),
125
+ 'limit' => 100,
126
+ ), $limits);
127
+
128
+ /** @var WPDB $wpdb */
129
+ global $wpdb;
130
+
131
+ $sql = "SELECT terms.term_id val, terms.name title"
132
+ ." FROM $wpdb->terms AS terms, $wpdb->term_taxonomy AS taxonomies"
133
+ ." WHERE terms.term_id = taxonomies.term_id AND taxonomies.term_id = taxonomies.term_taxonomy_id";
134
+
135
+ {
136
+ $prepare = array();
137
+
138
+ if ($limits['id']) {
139
+ $sql .= " AND terms.term_id IN ( "
140
+ . implode( ', ', array_fill( 1, count( $limits['id'] ), '%d' ) )
141
+ . " ) ";
142
+ $prepare = array_merge($prepare, $limits['id']);
143
+ }
144
+
145
+ if ($limits['taxonomy']) {
146
+ $sql .= " AND taxonomies.taxonomy IN ( "
147
+ . implode( ', ', array_fill( 1, count( $limits['taxonomy'] ), '%s' ) )
148
+ . " ) ";
149
+ $prepare = array_merge($prepare, array_keys($limits['taxonomy']));
150
+ }
151
+
152
+ if ($limits['title']) {
153
+ $sql .= " AND terms.name LIKE %s";
154
+ $prepare[] = '%'. $wpdb->esc_like( $limits['title'] ) .'%';
155
+ }
156
+ }
157
+
158
+ $sql .= " LIMIT ". intval($limits['limit']);
159
+
160
+ return $wpdb->get_results($wpdb->prepare($sql, $prepare), ARRAY_A);
161
+ }
162
+
163
+ private static function query_users(array $limits) {
164
+ $limits = array_merge(array(
165
+ 'name' => '',
166
+ 'role' => array(
167
+ 'editor' => true,
168
+ ),
169
+ 'id' => array( /* 1, 7, 120 */ ),
170
+ 'limit' => 100,
171
+ ), $limits);
172
+
173
+ /** @var WPDB $wpdb */
174
+ global $wpdb;
175
+
176
+ $sql = "SELECT users.id val, users.user_nicename title"
177
+ ." FROM $wpdb->users AS users, $wpdb->usermeta AS usermeta"
178
+ ." WHERE usermeta.user_id = users.ID";
179
+
180
+ {
181
+ $prepare = array();
182
+
183
+ if ($limits['id']) {
184
+ $sql .= " AND users.id IN ( "
185
+ . implode( ', ', array_fill( 1, count( $limits['id'] ), '%d' ) )
186
+ . " ) ";
187
+ $prepare = array_merge($prepare, $limits['id']);
188
+ }
189
+
190
+ if ($limits['role']) {
191
+ $sql .= " AND usermeta.meta_key = 'wp_capabilities' "
192
+ . "AND ( "
193
+ . implode( ' OR ',
194
+ array_fill( 1, count( $limits['role'] ), 'usermeta.meta_value LIKE %s' ) ) .
195
+ " ) ";
196
+
197
+ foreach ( $limits['role'] as $name ) {
198
+ $prepare[] = '%' . $wpdb->esc_like( $name ) . '%';
199
+ }
200
+ }
201
+
202
+ if ($limits['name']) {
203
+ $sql .= " AND users.user_nicename LIKE %s";
204
+ $prepare[] = '%'. $wpdb->esc_like( $limits['name'] ) .'%';
205
+ }
206
+ }
207
+
208
+ $sql .= " LIMIT ". intval($limits['limit']);
209
+
210
+ return $wpdb->get_results($wpdb->prepare($sql, $prepare), ARRAY_A);
211
+ }
212
+
213
  /**
214
  * @internal
215
  */
216
+ public static function _ajax_autocomplete() {
217
+ if (!current_user_can('edit_posts')) {
218
+ wp_send_json_error();
219
+ }
 
220
 
221
  $type = FW_Request::POST( 'data/type' );
222
+ $names = ($names = json_decode( FW_Request::POST( 'data/names' ), true )) ? $names : array();
223
  $title = FW_Request::POST( 'data/string' );
224
 
225
  $items = array();
226
 
227
  switch ( $type ) {
228
  case 'posts':
229
+ $items = self::query_posts(array(
230
+ 'type' => array_fill_keys($names, true),
231
+ 'title' => $title,
232
+ ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  break;
234
  case 'taxonomy':
235
+ $items = self::query_terms(array(
236
+ 'taxonomy' => array_fill_keys($names, true),
237
+ 'title' => $title,
238
+ ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  break;
240
  case 'users':
241
+ $items = self::query_users(array(
242
+ 'role' => array_fill_keys($names, true),
243
+ 'name' => $title,
244
+ ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  break;
246
  }
247
 
259
  * @internal
260
  */
261
  protected function _render( $id, $option, $data ) {
262
+ $population = $option['population'];
 
263
  $source = array();
264
+ $items = array();
265
 
266
  if ( isset( $option['population'] ) ) {
267
  switch ( $option['population'] ) {
268
  case 'array' :
269
  if ( isset( $option['choices'] ) && is_array( $option['choices'] ) ) {
270
+ foreach ($option['choices'] as $c_key => $c_val) {
271
+ $items[] = array(
272
+ 'val' => $c_key,
273
+ 'title' => $c_val,
274
+ );
275
+ }
276
  }
277
  break;
278
  case 'posts' :
279
  if ( isset( $option['source'] ) ) {
280
+ $source = is_array( $option['source'] ) ? $option['source'] : array( $option['source'] );
281
+ $items = self::query_posts(array(
282
+ 'type' => array_fill_keys($source, true),
283
+ 'id' => $data['value'],
284
+ 'limit' => $option['prepopulate'],
285
+ ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  }
287
  break;
288
  case 'taxonomy' :
289
  if ( isset( $option['source'] ) ) {
290
+ $source = is_array( $option['source'] ) ? $option['source'] : array( $option['source'] );
291
+ $items = self::query_terms(array(
292
+ 'taxonomy' => array_fill_keys($source, true),
293
+ 'id' => $data['value'],
294
+ 'limit' => $option['prepopulate'],
295
+ ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
  }
297
  break;
298
  case 'users' :
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  if ( isset( $option['source'] ) && ! empty( $option['source'] ) ) {
300
  $source = is_array( $option['source'] ) ? $option['source'] : array( $option['source'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  } else {
302
  $source = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  }
304
 
305
+ $items = self::query_users(array(
306
+ 'role' => array_fill_keys($source, true),
307
+ 'id' => $data['value'],
308
+ 'limit' => $option['prepopulate'],
309
+ ));
310
  break;
311
  default :
312
+ return '(Invalid <code>population</code> parameter)';
313
  }
314
 
315
+ $option['attr']['data-options'] = json_encode( $items );
316
  $option['attr']['data-population'] = $population;
317
  $option['attr']['data-source'] = json_encode( $source );
318
  $option['attr']['data-limit'] = ( intval( $option['limit'] ) > 0 ) ? $option['limit'] : 0;
319
  } else {
320
+ return '(The <code>population</code> parameter is required)';
321
  }
322
+
323
  if ( ! empty( $data['value'] ) ) {
324
  $data['value'] = implode( '/*/', $data['value'] );
325
  } else {
351
  fw()->backend->option_type( 'text' )->enqueue_static();
352
  }
353
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
  /**
355
  * @internal
356
  */
365
  }
366
  }
367
 
368
+ add_action( 'wp_ajax_fw_option_type_multi_select_autocomplete',
369
+ array( "FW_Option_Type_Multi_Select", '_ajax_autocomplete' ) );
 
 
 
370
  endif;
framework/includes/option-types/multi-select/static/css/style.css CHANGED
@@ -1,27 +1,12 @@
1
- .fw-option-type-multi-select.selectize-control.multi .selectize-input.has-items,
2
- .fw-option-type-multi-select .selectize-input {
3
- padding: 0 0 3px 3px;
4
- border-radius: 0;
5
- border: 1px solid #ddd;
6
- }
7
-
8
  .fw-option-type-multi-select .selectize-input {
9
  padding: 4px 6px;
10
  }
11
 
12
- .fw-option-type-multi-select.selectize-control.multi .selectize-input > div {
13
- margin: 3px 3px 0 0;
14
- }
15
-
16
  .fw-option-type-multi-select .selectize-input.focus.input-active.dropdown-active:before,
17
  .fw-option-type-multi-select .selectize-input.focus.input-active.dropdown-active:before {
18
  display: none;
19
  }
20
 
21
- .fw-option-type-multi-select .selectize-input.focus.input-active.dropdown-active:after {
22
- border-width: 5px 5px 0 5px;
23
- }
24
-
25
  .fw-backend-option-input-type-multi-select .fw-option-help-in-input {
26
  top: 4px !important;
27
  }
 
 
 
 
 
 
 
1
  .fw-option-type-multi-select .selectize-input {
2
  padding: 4px 6px;
3
  }
4
 
 
 
 
 
5
  .fw-option-type-multi-select .selectize-input.focus.input-active.dropdown-active:before,
6
  .fw-option-type-multi-select .selectize-input.focus.input-active.dropdown-active:before {
7
  display: none;
8
  }
9
 
 
 
 
 
10
  .fw-backend-option-input-type-multi-select .fw-option-help-in-input {
11
  top: 4px !important;
12
  }
framework/includes/option-types/multi-select/static/js/scripts.js CHANGED
@@ -1,69 +1,92 @@
1
  (function ($) {
2
- var fw_option_multi_select_initialize = function(item) {
3
- var population = item.attr('data-population');
4
- var source = item.attr('data-source');
5
- var limit = parseInt(item.attr('data-limit'));
6
- var xhr;
7
 
8
- item.selectize({
9
- maxItems: ( limit > 0 ) ? limit : null,
10
- delimiter: '/*/',
11
- valueField: 'val',
12
- labelField: 'title',
13
- searchField: 'title',
14
- options: JSON.parse(item.attr('data-options')),
15
- create: false,
16
- onType: function (value) {
17
- if (population == 'array') {
18
- return;
19
- }
20
-
21
- if (value.length < 2) {
22
- return;
23
- }
24
-
25
- this.load(function (callback) {
26
- xhr && xhr.abort();
27
-
28
- var data = {
29
- action: 'admin_action_get_ajax_response',
30
  data: {
31
  string: value,
32
  type: population,
33
  names: source
34
  }
35
- };
36
-
37
- xhr = $.post(
38
- ajaxurl,
39
- data,
40
- function (response) {
41
- callback(response.data)
42
  }
43
- )
44
- });
45
 
46
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  });
48
- };
49
 
50
- fwEvents.on('fw:options:init', function (data) {
51
- data.$elements
52
- .find('.fw-option-type-multi-select:not(.initialized)')
53
- .each(function () {
54
- fw_option_multi_select_initialize($(this));
 
55
  });
 
 
56
 
57
- /*
58
- * WARNING:
59
- *
60
- * data.$elements.find is intentionally looked up twice instead of cached
61
- * this is done because when fw_option_multi_select_initialize is called
62
- * the selectize plugin inserts an element which copies the
63
- * `fw-option-type-multi-select` class, thus making the cache invalid.
64
- */
65
  data.$elements
66
  .find('.fw-option-type-multi-select:not(.initialized)')
67
- .addClass('initialized');
 
68
  });
69
  })(jQuery);
1
  (function ($) {
2
+ var xhr,
3
+ optionsCache = {},
4
+ ajaxAutocompleteCallback = _.throttle(function(selectize, value, population, source, hash){
5
+ selectize.load(function(callback){
6
+ xhr && xhr.abort();
7
 
8
+ xhr = $.post(
9
+ ajaxurl,
10
+ {
11
+ action: 'fw_option_type_multi_select_autocomplete',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  data: {
13
  string: value,
14
  type: population,
15
  names: source
16
  }
17
+ },
18
+ function (response) {
19
+ if (!response.success) {
20
+ console.error('multi-select ajax error', response);
21
+ callback([]);
22
+ return;
 
23
  }
 
 
24
 
25
+ callback(response.data);
26
+
27
+ optionsCache[hash] = []; // transform object to array
28
+ $.each(selectize.options, function(i, o){
29
+ optionsCache[hash].push(o);
30
+ });
31
+ }
32
+ );
33
+ });
34
+ }, 300);
35
+
36
+ function init() {
37
+ var $this = $(this);
38
+
39
+ $this.one('fw:option-type:multi-select:init', function () {
40
+ var population = $this.attr('data-population'),
41
+ source = $this.attr('data-source'),
42
+ limit = parseInt($this.attr('data-limit')),
43
+ hash = fw.md5(JSON.stringify([population, source])),
44
+ options = (
45
+ typeof optionsCache[hash] == 'undefined'
46
+ ? JSON.parse($this.attr('data-options'))
47
+ : optionsCache[hash]
48
+ );
49
+
50
+ $this.selectize({
51
+ maxItems: ( limit > 0 ) ? limit : null,
52
+ delimiter: '/*/',
53
+ valueField: 'val',
54
+ labelField: 'title',
55
+ searchField: 'title',
56
+ options: options,
57
+ create: false,
58
+ onType: function (value) {
59
+ if (population == 'array' || value.length < 2) {
60
+ return;
61
+ }
62
+
63
+ ajaxAutocompleteCallback(this, value, population, source, hash);
64
+ }
65
+ });
66
+
67
+ $this.next()
68
+ .addClass('fw-selectize')
69
+ .find('> .selectize-input > input').css('width', '11px'); // more than padding left+right to make the cursor visible
70
+
71
+ $this.on('remove', function () {
72
+ $this.get(0).selectize.destroy();
73
+ });
74
  });
 
75
 
76
+ if ($this.val().length) { // there are values that needs to be show right away
77
+ $this.trigger('fw:option-type:multi-select:init');
78
+ } else {
79
+ $this.one('focus', function(){
80
+ $this.trigger('fw:option-type:multi-select:init');
81
+ $this.get(0).selectize.focus();
82
  });
83
+ }
84
+ };
85
 
86
+ fwEvents.on('fw:options:init', function (data) {
 
 
 
 
 
 
 
87
  data.$elements
88
  .find('.fw-option-type-multi-select:not(.initialized)')
89
+ .addClass('initialized')
90
+ .each(init);
91
  });
92
  })(jQuery);
framework/includes/option-types/multi-upload/class-fw-option-type-multi-upload.php CHANGED
@@ -245,5 +245,4 @@ class FW_Option_Type_Multi_Upload extends FW_Option_Type
245
  }
246
  return $return_arr;
247
  }
248
- }
249
- FW_Option_Type::register('FW_Option_Type_Multi_Upload');
245
  }
246
  return $return_arr;
247
  }
248
+ }
 
framework/includes/option-types/multi/class-fw-option-type-multi.php CHANGED
@@ -95,5 +95,4 @@ class FW_Option_Type_Multi extends FW_Option_Type
95
  'value' => array(),
96
  );
97
  }
98
- }
99
- FW_Option_Type::register('FW_Option_Type_Multi');
95
  'value' => array(),
96
  );
97
  }
98
+ }
 
framework/includes/option-types/oembed/class-fw-option-type-oembed.php CHANGED
@@ -116,9 +116,7 @@ class FW_Option_Type_Oembed extends FW_Option_Type {
116
  }
117
  }
118
 
119
- FW_Option_Type::register( 'FW_Option_Type_Oembed' );
120
-
121
  add_action(
122
  'wp_ajax_get_oembed_response',
123
  array( "FW_Option_Type_Oembed", '_action_get_oembed_response' )
124
- );
116
  }
117
  }
118
 
 
 
119
  add_action(
120
  'wp_ajax_get_oembed_response',
121
  array( "FW_Option_Type_Oembed", '_action_get_oembed_response' )
122
+ );
framework/includes/option-types/popup/class-fw-option-type-popup.php CHANGED
@@ -194,6 +194,4 @@ class FW_Option_Type_Popup extends FW_Option_Type {
194
  );
195
  }
196
 
197
- }
198
-
199
- FW_Option_Type::register( 'FW_Option_Type_Popup' );
194
  );
195
  }
196
 
197
+ }
 
 
framework/includes/option-types/radio-text/class-fw-option-type-radio-text.php CHANGED
@@ -120,5 +120,4 @@ class FW_Option_Type_Radio_Text extends FW_Option_Type
120
  return $selected;
121
  }
122
  }
123
- }
124
- FW_Option_Type::register('FW_Option_Type_Radio_Text');
120
  return $selected;
121
  }
122
  }
123
+ }
 
framework/includes/option-types/range-slider/class-fw-option-type-range-slider.php CHANGED
@@ -149,6 +149,4 @@ class FW_Option_Type_Range_Slider extends FW_Option_Type {
149
  return $option;
150
  }
151
 
152
- }
153
-
154
- FW_Option_Type::register( 'FW_Option_Type_Range_Slider' );
149
  return $option;
150
  }
151
 
152
+ }
 
 
framework/includes/option-types/rgba-color-picker/class-fw-option-type-rgba-color-picker.php CHANGED
@@ -99,6 +99,4 @@ class FW_Option_Type_Rgba_Color_Picker extends FW_Option_Type {
99
  'palettes'=> true
100
  );
101
  }
102
- }
103
-
104
- FW_Option_Type::register( 'FW_Option_Type_Rgba_Color_Picker' );
99
  'palettes'=> true
100
  );
101
  }
102
+ }
 
 
framework/includes/option-types/simple.php CHANGED
@@ -63,8 +63,6 @@ class FW_Option_Type_Hidden extends FW_Option_Type {
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';
@@ -114,8 +112,6 @@ class FW_Option_Type_Text extends FW_Option_Type {
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';
@@ -145,8 +141,6 @@ class FW_Option_Type_Short_Text extends FW_Option_Type_Text {
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';
@@ -196,8 +190,6 @@ class FW_Option_Type_Password extends FW_Option_Type {
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';
@@ -254,8 +246,6 @@ class FW_Option_Type_Textarea extends FW_Option_Type {
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';
@@ -330,8 +320,6 @@ class FW_Option_Type_Html extends FW_Option_Type {
330
  }
331
  }
332
 
333
- FW_Option_Type::register( 'FW_Option_Type_Html' );
334
-
335
  /**
336
  * Same html but displayed in fixed width
337
  */
@@ -348,8 +336,6 @@ class FW_Option_Type_Html_Fixed extends FW_Option_Type_Html {
348
  }
349
  }
350
 
351
- FW_Option_Type::register( 'FW_Option_Type_Html_Fixed' );
352
-
353
  /**
354
  * Same html but displayed in full width
355
  */
@@ -366,7 +352,6 @@ class FW_Option_Type_Html_Full extends FW_Option_Type_Html {
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() {
@@ -456,8 +441,6 @@ class FW_Option_Type_Checkbox extends FW_Option_Type {
456
  }
457
  }
458
 
459
- FW_Option_Type::register( 'FW_Option_Type_Checkbox' );
460
-
461
  /**
462
  * Checkboxes list
463
  */
@@ -588,8 +571,6 @@ class FW_Option_Type_Checkboxes extends FW_Option_Type {
588
  }
589
  }
590
 
591
- FW_Option_Type::register( 'FW_Option_Type_Checkboxes' );
592
-
593
  /**
594
  * Radio list
595
  */
@@ -708,8 +689,6 @@ class FW_Option_Type_Radio extends FW_Option_Type {
708
  }
709
  }
710
 
711
- FW_Option_Type::register( 'FW_Option_Type_Radio' );
712
-
713
  /**
714
  * Select
715
  */
@@ -861,8 +840,6 @@ class FW_Option_Type_Select extends FW_Option_Type {
861
  }
862
  }
863
 
864
- FW_Option_Type::register( 'FW_Option_Type_Select' );
865
-
866
  class FW_Option_Type_Short_Select extends FW_Option_Type_Select {
867
  public function get_type() {
868
  return 'short-select';
@@ -892,8 +869,6 @@ class FW_Option_Type_Short_Select extends FW_Option_Type_Select {
892
  }
893
  }
894
 
895
- FW_Option_Type::register( 'FW_Option_Type_Short_Select' );
896
-
897
  /**
898
  * Select Multiple
899
  */
@@ -1020,9 +995,6 @@ class FW_Option_Type_Select_Multiple extends FW_Option_Type_Select {
1020
  }
1021
  }
1022
 
1023
- FW_Option_Type::register( 'FW_Option_Type_Select_Multiple' );
1024
-
1025
-
1026
  class FW_Option_Type_Unique extends FW_Option_Type
1027
  {
1028
  private static $ids = array();
@@ -1178,7 +1150,6 @@ class FW_Option_Type_Unique extends FW_Option_Type
1178
  return $value;
1179
  }
1180
  }
1181
- FW_Option_Type::register('FW_Option_Type_Unique');
1182
 
1183
  /**
1184
  * Input for Google Maps API Key which is stored in a wp_option
@@ -1234,6 +1205,4 @@ class FW_Option_Type_GMap_Key extends FW_Option_Type_Text {
1234
  }
1235
  return parent::_storage_save( $id, $option, $value, $params );
1236
  }
1237
- }
1238
-
1239
- FW_Option_Type::register( 'FW_Option_Type_GMap_Key' );
63
  }
64
  }
65
 
 
 
66
  class FW_Option_Type_Text extends FW_Option_Type {
67
  public function get_type() {
68
  return 'text';
112
  }
113
  }
114
 
 
 
115
  class FW_Option_Type_Short_Text extends FW_Option_Type_Text {
116
  public function get_type() {
117
  return 'short-text';
141
  }
142
  }
143
 
 
 
144
  class FW_Option_Type_Password extends FW_Option_Type {
145
  public function get_type() {
146
  return 'password';
190
  }
191
  }
192
 
 
 
193
  class FW_Option_Type_Textarea extends FW_Option_Type {
194
  public function get_type() {
195
  return 'textarea';
246
  }
247
  }
248
 
 
 
249
  class FW_Option_Type_Html extends FW_Option_Type {
250
  public function get_type() {
251
  return 'html';
320
  }
321
  }
322
 
 
 
323
  /**
324
  * Same html but displayed in fixed width
325
  */
336
  }
337
  }
338
 
 
 
339
  /**
340
  * Same html but displayed in full width
341
  */
352
  }
353
  }
354
 
 
355
 
356
  class FW_Option_Type_Checkbox extends FW_Option_Type {
357
  public function get_type() {
441
  }
442
  }
443
 
 
 
444
  /**
445
  * Checkboxes list
446
  */
571
  }
572
  }
573
 
 
 
574
  /**
575
  * Radio list
576
  */
689
  }
690
  }
691
 
 
 
692
  /**
693
  * Select
694
  */
840
  }
841
  }
842
 
 
 
843
  class FW_Option_Type_Short_Select extends FW_Option_Type_Select {
844
  public function get_type() {
845
  return 'short-select';
869
  }
870
  }
871
 
 
 
872
  /**
873
  * Select Multiple
874
  */
995
  }
996
  }
997
 
 
 
 
998
  class FW_Option_Type_Unique extends FW_Option_Type
999
  {
1000
  private static $ids = array();
1150
  return $value;
1151
  }
1152
  }
 
1153
 
1154
  /**
1155
  * Input for Google Maps API Key which is stored in a wp_option
1205
  }
1206
  return parent::_storage_save( $id, $option, $value, $params );
1207
  }
1208
+ }
 
 
framework/includes/option-types/slider/class-fw-option-type-short-slider.php CHANGED
@@ -12,6 +12,4 @@ class FW_Option_Type_Slider_Short extends FW_Option_Type_Slider {
12
 
13
  return parent::_render( $id, $option, $data );
14
  }
15
- }
16
-
17
- FW_Option_Type::register( 'FW_Option_Type_Slider_Short' );
12
 
13
  return parent::_render( $id, $option, $data );
14
  }
15
+ }
 
 
framework/includes/option-types/slider/class-fw-option-type-slider.php CHANGED
@@ -111,6 +111,4 @@ class FW_Option_Type_Slider extends FW_Option_Type {
111
  }
112
  }
113
 
114
- }
115
-
116
- FW_Option_Type::register( 'FW_Option_Type_Slider' );
111
  }
112
  }
113
 
114
+ }
 
 
framework/includes/option-types/switch/class-fw-option-type-switch.php CHANGED
@@ -167,5 +167,4 @@ class FW_Option_Type_Switch extends FW_Option_Type
167
  ),
168
  );
169
  }
170
- }
171
- FW_Option_Type::register('FW_Option_Type_Switch');
167
  ),
168
  );
169
  }
170
+ }
 
framework/includes/option-types/typography-v2/class-fw-option-type-typography-v2.php CHANGED
@@ -178,6 +178,4 @@ class FW_Option_Type_Typography_v2 extends FW_Option_Type {
178
  );
179
  }
180
 
181
- }
182
-
183
- FW_Option_Type::register( 'FW_Option_Type_Typography_v2' );
178
  );
179
  }
180
 
181
+ }
 
 
framework/includes/option-types/typography/class-fw-option-type-typography.php CHANGED
@@ -142,6 +142,4 @@ class FW_Option_Type_Typography extends FW_Option_Type
142
  {
143
  return 'fixed';
144
  }
145
- }
146
-
147
- FW_Option_Type::register('FW_Option_Type_Typography');
142
  {
143
  return 'fixed';
144
  }
145
+ }
 
 
framework/includes/option-types/upload/class-fw-option-type-upload.php CHANGED
@@ -230,5 +230,4 @@ class FW_Option_Type_Upload extends FW_Option_Type
230
  return $defaults['value'];
231
  }
232
  }
233
- }
234
- FW_Option_Type::register('FW_Option_Type_Upload');
230
  return $defaults['value'];
231
  }
232
  }
233
+ }
 
framework/includes/option-types/wp-editor/class-fw-option-type-wp-editor.php CHANGED
@@ -167,6 +167,4 @@ class FW_Option_Type_Wp_Editor extends FW_Option_Type {
167
  public function _get_backend_width_type() {
168
  return 'auto';
169
  }
170
- }
171
-
172
- FW_Option_Type::register( 'FW_Option_Type_Wp_Editor' );
167
  public function _get_backend_width_type() {
168
  return 'auto';
169
  }
170
+ }
 
 
framework/includes/option-types/wp-editor/static/scripts.js CHANGED
@@ -44,7 +44,10 @@
44
  var editor = e.target,
45
  id = editor.id;
46
 
47
- editor.on('change', function(){ editor.save(); });
 
 
 
48
 
49
  /**
50
  * Fixes when wpautop is false
44
  var editor = e.target,
45
  id = editor.id;
46
 
47
+ editor.on('change', function(){
48
+ editor.save();
49
+ $textarea.trigger('change'); // fixes https://github.com/ThemeFuse/Unyson/issues/2273
50
+ });
51
 
52
  /**
53
  * Fixes when wpautop is false
framework/manifest.php CHANGED
@@ -4,4 +4,4 @@ $manifest = array();
4
 
5
  $manifest['name'] = __('Unyson', 'fw');
6
 
7
- $manifest['version'] = '2.6.10';
4
 
5
  $manifest['name'] = __('Unyson', 'fw');
6
 
7
+ $manifest['version'] = '2.6.11';
framework/static/css/backend-options.css CHANGED
@@ -1210,25 +1210,6 @@ body.rtl .fw-backend-option-design-default.with-help > .fw-backend-option-label
1210
  /* end: modal fix */
1211
 
1212
  /* Add Selectize support for all selects with fw-selectize class */
1213
- .fw-selectize.selectize-control.single .selectize-input {
1214
- background: none;
1215
- margin: 1px;
1216
- vertical-align: middle;
1217
- border: 1px solid #dddddd;
1218
- color: #333333;
1219
- height: 28px;
1220
- line-height: 27px;
1221
- font-size: 14px;
1222
- padding: 0 6px;
1223
-
1224
- -webkit-border-radius: 0;
1225
- -moz-border-radius: 0;
1226
- border-radius: 0;
1227
-
1228
- -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .07);
1229
- -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .07);
1230
- box-shadow: inset 0 1px 2px rgba(0, 0, 0, .07);
1231
- }
1232
 
1233
  .fw-selectize.selectize-control.single .selectize-input:before {
1234
  height: 0;
@@ -1243,6 +1224,53 @@ body.rtl .fw-backend-option-design-default.with-help > .fw-backend-option-label
1243
  border-color: #000000 transparent transparent transparent;
1244
  }
1245
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1246
  .fw-selectize.selectize-control .selectize-dropdown {
1247
  margin: 0 1px;
1248
  border: none;
1210
  /* end: modal fix */
1211
 
1212
  /* Add Selectize support for all selects with fw-selectize class */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1213
 
1214
  .fw-selectize.selectize-control.single .selectize-input:before {
1215
  height: 0;
1224
  border-color: #000000 transparent transparent transparent;
1225
  }
1226
 
1227
+ .fw-selectize.selectize-control > .selectize-input,
1228
+ .fw-selectize.selectize-control > .selectize-input.has-items,
1229
+ .fw-selectize.selectize-control > .selectize-input.input-active {
1230
+ display: block !important;
1231
+ padding: 0;
1232
+ margin: 1px;
1233
+ border-radius: 0;
1234
+ border: 1px solid #ddd;
1235
+ color: #333333;
1236
+
1237
+ -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.07);
1238
+ box-shadow: inset 0 1px 2px rgba(0,0,0,.07);
1239
+ }
1240
+
1241
+ .fw-selectize.selectize-control > .selectize-input > input {
1242
+ padding: 2px 5px !important;
1243
+ height: auto;
1244
+ font-size: 14px;
1245
+ vertical-align: middle;
1246
+ }
1247
+
1248
+ .fw-modal .media-frame .fw-selectize.selectize-control > .selectize-input > input {
1249
+ height: 26px;
1250
+ }
1251
+
1252
+ .fw-selectize.selectize-control .selectize-input > div {
1253
+ vertical-align: middle;
1254
+ }
1255
+
1256
+ .fw-selectize.selectize-control.single .selectize-input > div {
1257
+ padding: 2px 5px;
1258
+ font-size: 14px;
1259
+ }
1260
+
1261
+ .fw-modal .media-frame .fw-selectize.selectize-control.single .selectize-input > div {
1262
+ padding: 4px 5px;
1263
+ }
1264
+
1265
+ .fw-selectize.selectize-control.multi .selectize-input > div {
1266
+ margin: 2px;
1267
+ padding: 0 3px;
1268
+ }
1269
+
1270
+ .fw-modal .media-frame .fw-selectize.selectize-control.multi .selectize-input > div {
1271
+ padding: 2px 5px;
1272
+ }
1273
+
1274
  .fw-selectize.selectize-control .selectize-dropdown {
1275
  margin: 0 1px;
1276
  border: none;
framework/static/css/fw.css CHANGED
@@ -2945,7 +2945,10 @@ body.wp-customizer > div:not(.fw-modal) > .media-modal-backdrop {
2945
  transition: opacity .3s ease-in-out;
2946
  }
2947
 
2948
- .fw-modal.fw-modal-open > .media-modal > .media-modal-content {
 
 
 
2949
  -webkit-animation: fwGrowIn .3s ease-in-out;
2950
  -moz-animation: fwGrowIn .3s ease-in-out;
2951
  -ms-animation: fwGrowIn .3s ease-in-out;
@@ -2953,6 +2956,32 @@ body.wp-customizer > div:not(.fw-modal) > .media-modal-backdrop {
2953
  animation: fwGrowIn .3s ease-in-out;
2954
  }
2955
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2956
  .fw-modal > .media-modal > .media-modal-close {
2957
  opacity: 0;
2958
 
@@ -2979,17 +3008,6 @@ body.wp-customizer > div:not(.fw-modal) > .media-modal-backdrop {
2979
  opacity: .0;
2980
  }
2981
 
2982
- .fw-modal.fw-modal-closing > .media-modal > .media-modal-content {
2983
- -webkit-animation: fwGrowOut .3s ease-in-out;
2984
- -moz-animation: fwGrowOut .3s ease-in-out;
2985
- -ms-animation: fwGrowOut .3s ease-in-out;
2986
- -o-animation: fwGrowOut .3s ease-in-out;
2987
- animation: fwGrowOut .3s ease-in-out;
2988
-
2989
- -webkit-animation-fill-mode: forwards; /* Chrome, Safari, Opera */
2990
- animation-fill-mode: forwards;
2991
- }
2992
-
2993
  .fw-modal.fw-modal-closing > .media-modal > .media-modal-close {
2994
  opacity: 0;
2995
 
2945
  transition: opacity .3s ease-in-out;
2946
  }
2947
 
2948
+ /**
2949
+ * Specificity score: 5
2950
+ */
2951
+ .fw-modal.fw-sole-modal.fw-modal-opening > .media-modal > .media-modal-content {
2952
  -webkit-animation: fwGrowIn .3s ease-in-out;
2953
  -moz-animation: fwGrowIn .3s ease-in-out;
2954
  -ms-animation: fwGrowIn .3s ease-in-out;
2956
  animation: fwGrowIn .3s ease-in-out;
2957
  }
2958
 
2959
+ /**
2960
+ * Specificity score: 5
2961
+ */
2962
+ .fw-modal:not(.fw-sole-modal).fw-modal-open > .media-modal > .media-modal-content {
2963
+ -webkit-animation: fwGrowIn .3s ease-in-out;
2964
+ -moz-animation: fwGrowIn .3s ease-in-out;
2965
+ -ms-animation: fwGrowIn .3s ease-in-out;
2966
+ -o-animation: fwGrowIn .3s ease-in-out;
2967
+ animation: fwGrowIn .3s ease-in-out;
2968
+ }
2969
+
2970
+ /**
2971
+ * Dirty hack to keep specificity intact
2972
+ * Specificity score: 5.1
2973
+ */
2974
+ body.wp-core-ui .fw-modal.fw-modal-closing > .media-modal > .media-modal-content {
2975
+ -webkit-animation: fwGrowOut .3s ease-in-out;
2976
+ -moz-animation: fwGrowOut .3s ease-in-out;
2977
+ -ms-animation: fwGrowOut .3s ease-in-out;
2978
+ -o-animation: fwGrowOut .3s ease-in-out;
2979
+ animation: fwGrowOut .3s ease-in-out;
2980
+
2981
+ -webkit-animation-fill-mode: forwards; /* Chrome, Safari, Opera */
2982
+ animation-fill-mode: forwards;
2983
+ }
2984
+
2985
  .fw-modal > .media-modal > .media-modal-close {
2986
  opacity: 0;
2987
 
3008
  opacity: .0;
3009
  }
3010
 
 
 
 
 
 
 
 
 
 
 
 
3011
  .fw-modal.fw-modal-closing > .media-modal > .media-modal-close {
3012
  opacity: 0;
3013
 
framework/static/js/fw.js CHANGED
@@ -867,6 +867,18 @@ fw.getQueryString = function(name) {
867
 
868
  $modalWrapper.addClass('fw-modal-open');
869
 
 
 
 
 
 
 
 
 
 
 
 
 
870
  modalsStack.push($modalWrapper.find('.media-modal'));
871
 
872
  // Resize .fw-options-tabs-contents to fit entire window
@@ -1193,20 +1205,29 @@ fw.getValuesFromServer = function (data) {
1193
  buttons = [
1194
  {
1195
  style: 'primary',
1196
- text: _fw_localized.l10n.save,
1197
  priority: 40,
1198
- click: triggerSubmit
1199
- },
1200
- {
1201
- style: '',
1202
- text: _fw_localized.l10n.reset,
1203
- priority: -1,
1204
  click: function () {
1205
- modal.content.resetForm();
 
 
 
 
1206
  }
1207
  }
1208
  ];
1209
 
 
 
 
 
 
 
 
 
 
 
 
1210
  /**
1211
  * Sometimes we want an apply button in order to save changes
1212
  * that will not trigger a modal close.
@@ -1842,6 +1863,8 @@ fw.soleModal = (function(){
1842
  },
1843
  setSize: function(width, height) {
1844
  var $size = this.$modal.find('> .media-modal');
 
 
1845
 
1846
  if (
1847
  $size.height() != height
@@ -1854,6 +1877,10 @@ fw.soleModal = (function(){
1854
  }, this.animationTime);
1855
  }
1856
 
 
 
 
 
1857
  $size = undefined;
1858
  },
1859
  /**
@@ -2139,6 +2166,10 @@ fw.soleModal = (function(){
2139
  }
2140
 
2141
  jQuery.each(messages, function(messageId, message){
 
 
 
 
2142
  typeHtml.push(
2143
  '<li>'+
2144
  '<h2 class="'+ typeMessageClass +'"><span class="'+ typeIconClass +'"></span> '+ typeTitle +'</h2>'+
@@ -2165,11 +2196,11 @@ fw.soleModal = (function(){
2165
  * Usage:
2166
  *
2167
  * var confirm = fw.soleConfirm.create();
2168
- * confirm.result.then(function (confirm_object) {
2169
  * // SUCCESS!!
2170
  * });
2171
  *
2172
- * confirm.result.fail(function (confirm_object) {
2173
  * // FAIL!!
2174
  * });
2175
  *
@@ -2202,7 +2233,12 @@ fw.soleConfirm = (function ($) {
2202
  this.opts = _.extend({
2203
  severity: 'info', // warning | info
2204
  message: null,
2205
- backdrop: null
 
 
 
 
 
2206
  }, opts);
2207
  }
2208
 
@@ -2235,11 +2271,14 @@ fw.soleConfirm = (function ($) {
2235
  showCloseButton: false,
2236
  allowClose: false, // a confirm window can't be closed on click of it's backdrop
2237
  backdrop: this.opts.backdrop,
2238
- customClass: 'fw-sole-confirm-modal fw-sole-confirm-' + this.opts.severity,
2239
  updateIfCurrent: true,
2240
 
2241
  afterOpenStart: _.bind(this._fireEvents, this),
2242
- afterCloseStart: _.bind(this._teardownEvents, this)
 
 
 
2243
  });
2244
  };
2245
 
@@ -2252,12 +2291,29 @@ fw.soleConfirm = (function ($) {
2252
  //////////////////
2253
 
2254
  Confirm.prototype._fireEvents = function ($modal) {
 
 
2255
  $modal.find('.fw-sole-confirm-button')
 
 
 
2256
  .on('click.fw-sole-confirm', _.bind(this._handleClose, this));
 
 
 
 
2257
  };
2258
 
2259
  Confirm.prototype._teardownEvents = function ($modal) {
2260
- $modal.find('.fw-sole-confirm-button').off('click.fw-sole-confirm');
 
 
 
 
 
 
 
 
2261
  };
2262
 
2263
  Confirm.prototype._checkIsSet = function () {
@@ -2267,14 +2323,49 @@ fw.soleConfirm = (function ($) {
2267
  };
2268
 
2269
  Confirm.prototype._handleClose = function (event) {
2270
- var action = $(event.target).attr('data-fw-sole-confirm-action');
2271
- var id = $(event.target).attr('data-fw-sole-confirm-id');
 
 
 
 
 
 
 
 
 
 
 
 
2272
  var confirm = hashMap[id];
2273
 
2274
  if (confirm) {
2275
- _.contains(['reject', 'resolve'], action) &&
2276
- confirm.result[action](this) &&
2277
- confirm.hide();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2278
 
2279
  confirm.destroy();
2280
  confirm = null;
@@ -2282,28 +2373,34 @@ fw.soleConfirm = (function ($) {
2282
  };
2283
 
2284
  Confirm.prototype._getHtml = function () {
 
 
 
 
 
 
2285
  var iconClass = 'dashicons-' + this.opts.severity;
2286
  var icon = '<span class="dashicons ' + iconClass + '"></span>';
2287
  var heading = '<h1>' + fw.capitalizeFirstLetter(this.opts.severity) + '</h1>';
2288
  var message = this.opts.message ? '<p>' + this.opts.message + '</p>' : '';
2289
 
 
 
2290
  var cancelButton = $('<button>', {
2291
- html: _fw_localized.l10n.cancel
2292
  }).attr({
2293
  'data-fw-sole-confirm-action': 'reject',
2294
- 'data-fw-sole-confirm-id': this.id,
2295
  type: 'button',
2296
  }).addClass('fw-sole-confirm-button button');
2297
 
2298
  var okButton = $('<button>', {
2299
- html: _fw_localized.l10n.ok
2300
  }).attr({
2301
  'data-fw-sole-confirm-action': 'resolve',
2302
- 'data-fw-sole-confirm-id': this.id,
2303
  type: 'button',
2304
  }).addClass('fw-sole-confirm-button button button-primary');
2305
 
2306
- return icon + heading + message + selfHtml(cancelButton) + selfHtml(okButton);
2307
 
2308
  function selfHtml (el) { return $('<div>').append(el).html(); }
2309
  };
867
 
868
  $modalWrapper.addClass('fw-modal-open');
869
 
870
+ /**
871
+ * We probably don't need this class anymore due to the
872
+ * fact that we hacked CSS specificity away.
873
+ *
874
+ * I'll be keeping it here for integrity with fw.soleModal.
875
+ */
876
+ $modalWrapper.addClass('fw-modal-opening');
877
+
878
+ setTimeout(function () {
879
+ $modalWrapper.removeClass('fw-modal-opening');
880
+ }, 300);
881
+
882
  modalsStack.push($modalWrapper.find('.media-modal'));
883
 
884
  // Resize .fw-options-tabs-contents to fit entire window
1205
  buttons = [
1206
  {
1207
  style: 'primary',
1208
+ text: settings.saveText || _fw_localized.l10n.save,
1209
  priority: 40,
 
 
 
 
 
 
1210
  click: function () {
1211
+ if (settings.shouldSaveWithoutClose) {
1212
+ modal.frame.$el.addClass('fw-options-modal-no-close');
1213
+ }
1214
+
1215
+ triggerSubmit();
1216
  }
1217
  }
1218
  ];
1219
 
1220
+ if (! settings.disableResetButton) {
1221
+ buttons = buttons.concat([{
1222
+ style: '',
1223
+ text: _fw_localized.l10n.reset,
1224
+ priority: -1,
1225
+ click: function () {
1226
+ modal.content.resetForm();
1227
+ }
1228
+ }]);
1229
+ }
1230
+
1231
  /**
1232
  * Sometimes we want an apply button in order to save changes
1233
  * that will not trigger a modal close.
1863
  },
1864
  setSize: function(width, height) {
1865
  var $size = this.$modal.find('> .media-modal');
1866
+ var $modal = this.$modal;
1867
+ $modal.addClass('fw-modal-opening');
1868
 
1869
  if (
1870
  $size.height() != height
1877
  }, this.animationTime);
1878
  }
1879
 
1880
+ setTimeout(function () {
1881
+ $modal.removeClass('fw-modal-opening');
1882
+ }, this.animationTime);
1883
+
1884
  $size = undefined;
1885
  },
1886
  /**
2166
  }
2167
 
2168
  jQuery.each(messages, function(messageId, message){
2169
+ if (!typeTitle.length) {
2170
+ return;
2171
+ }
2172
+
2173
  typeHtml.push(
2174
  '<li>'+
2175
  '<h2 class="'+ typeMessageClass +'"><span class="'+ typeIconClass +'"></span> '+ typeTitle +'</h2>'+
2196
  * Usage:
2197
  *
2198
  * var confirm = fw.soleConfirm.create();
2199
+ * confirm.result.then(function (data) {
2200
  * // SUCCESS!!
2201
  * });
2202
  *
2203
+ * confirm.result.fail(function (data) {
2204
  * // FAIL!!
2205
  * });
2206
  *
2233
  this.opts = _.extend({
2234
  severity: 'info', // warning | info
2235
  message: null,
2236
+ backdrop: null,
2237
+ renderFunction: null,
2238
+ shouldResolvePromise: function (confirm, el, action) { return true; },
2239
+ okHTML: _fw_localized.l10n.ok,
2240
+ cancelHTML: _fw_localized.l10n.cancel,
2241
+ customClass: ''
2242
  }, opts);
2243
  }
2244
 
2271
  showCloseButton: false,
2272
  allowClose: false, // a confirm window can't be closed on click of it's backdrop
2273
  backdrop: this.opts.backdrop,
2274
+ customClass: 'fw-sole-confirm-modal fw-sole-confirm-' + this.opts.severity + ' ' + this.opts.customClass,
2275
  updateIfCurrent: true,
2276
 
2277
  afterOpenStart: _.bind(this._fireEvents, this),
2278
+ afterCloseStart: _.bind(this._teardownEvents, this),
2279
+
2280
+ onFireEvents: jQuery.noop,
2281
+ onTeardownEvents: jQuery.noop
2282
  });
2283
  };
2284
 
2291
  //////////////////
2292
 
2293
  Confirm.prototype._fireEvents = function ($modal) {
2294
+ $modal.attr('data-fw-sole-confirm-id', this.id);
2295
+
2296
  $modal.find('.fw-sole-confirm-button')
2297
+ .add(
2298
+ $modal.find('.media-modal-backdrop')
2299
+ )
2300
  .on('click.fw-sole-confirm', _.bind(this._handleClose, this));
2301
+
2302
+ if (this.opts.onFireEvents) {
2303
+ this.opts.onFireEvents(this, $modal[0]);
2304
+ }
2305
  };
2306
 
2307
  Confirm.prototype._teardownEvents = function ($modal) {
2308
+ $modal.find('.fw-sole-confirm-button')
2309
+ .add(
2310
+ $modal.find('.media-modal-backdrop')
2311
+ )
2312
+ .off('click.fw-sole-confirm');
2313
+
2314
+ if (this.opts.onTeardownEvents) {
2315
+ this.opts.onTeardownEvents(this, $modal[0]);
2316
+ }
2317
  };
2318
 
2319
  Confirm.prototype._checkIsSet = function () {
2323
  };
2324
 
2325
  Confirm.prototype._handleClose = function (event) {
2326
+ event.preventDefault();
2327
+
2328
+ var $el = $(event.target);
2329
+
2330
+ if ($el.hasClass('media-modal-backdrop')) {
2331
+
2332
+ // do not do any transformation on $el here by intent
2333
+
2334
+ } else if (! $el.hasClass('fw-sole-confirm-button')) {
2335
+ $el = $el.closest('.fw-sole-confirm-button');
2336
+ }
2337
+
2338
+ var action = $el.attr('data-fw-sole-confirm-action') || 'reject';
2339
+ var id = $el.closest('.fw-sole-modal').attr('data-fw-sole-confirm-id');
2340
  var confirm = hashMap[id];
2341
 
2342
  if (confirm) {
2343
+ var modal_container = $el.closest('.fw-sole-modal')[0];
2344
+
2345
+ if (action === 'reject') {
2346
+ confirm.result.reject({
2347
+ confirm: confirm,
2348
+ modal_container: modal_container
2349
+ });
2350
+ } else {
2351
+ var shouldHideAfterResolve = confirm.opts.shouldResolvePromise(
2352
+ confirm, modal_container
2353
+ );
2354
+
2355
+ if (! shouldHideAfterResolve) {
2356
+ return;
2357
+ }
2358
+
2359
+ // probably keep this syntax for another actions in future
2360
+ _.contains(['resolve'], action) &&
2361
+ confirm.result[action]({
2362
+ confirm: confirm,
2363
+ modal_container: $el.closest('.fw-sole-modal')[0]
2364
+ });
2365
+
2366
+ }
2367
+
2368
+ confirm.hide();
2369
 
2370
  confirm.destroy();
2371
  confirm = null;
2373
  };
2374
 
2375
  Confirm.prototype._getHtml = function () {
2376
+ if (this.opts.renderFunction) {
2377
+ return this.opts.renderFunction(this);
2378
+ }
2379
+
2380
+ var topHtml = '';
2381
+
2382
  var iconClass = 'dashicons-' + this.opts.severity;
2383
  var icon = '<span class="dashicons ' + iconClass + '"></span>';
2384
  var heading = '<h1>' + fw.capitalizeFirstLetter(this.opts.severity) + '</h1>';
2385
  var message = this.opts.message ? '<p>' + this.opts.message + '</p>' : '';
2386
 
2387
+ topHtml = icon + heading + message;
2388
+
2389
  var cancelButton = $('<button>', {
2390
+ html: this.opts.cancelHTML
2391
  }).attr({
2392
  'data-fw-sole-confirm-action': 'reject',
 
2393
  type: 'button',
2394
  }).addClass('fw-sole-confirm-button button');
2395
 
2396
  var okButton = $('<button>', {
2397
+ html: this.opts.okHTML
2398
  }).attr({
2399
  'data-fw-sole-confirm-action': 'resolve',
 
2400
  type: 'button',
2401
  }).addClass('fw-sole-confirm-button button button-primary');
2402
 
2403
+ return topHtml + selfHtml(cancelButton) + selfHtml(okButton);
2404
 
2405
  function selfHtml (el) { return $('<div>').append(el).html(); }
2406
  };
framework/views/backend-settings-form.php CHANGED
@@ -250,17 +250,26 @@
250
 
251
  var noErrors = _.isEmpty(ajaxData.flash_messages.error) && _.isEmpty(ajaxData.flash_messages.warning);
252
 
253
- fw.soleModal.show(
254
- 'fw-options-ajax-save-success',
255
- '<div style="margin: 0 35px;">'+ fw.soleModal.renderFlashMessages(ajaxData.flash_messages) +'</div>',
256
- {
257
- autoHide: noErrors
258
- ? 1000 // hide fast the message if everything went fine
259
- : 10000,
260
- showCloseButton: false,
261
- hidePrevious: noErrors ? false : true // close and open popup when there are errors
262
- }
263
- );
 
 
 
 
 
 
 
 
 
264
  } while(false);
265
 
266
  /**
250
 
251
  var noErrors = _.isEmpty(ajaxData.flash_messages.error) && _.isEmpty(ajaxData.flash_messages.warning);
252
 
253
+ // remove success messages, do not make user wait
254
+ ajaxData.flash_messages = _.omit(ajaxData.flash_messages, 'success');
255
+
256
+ var modalHtml = fw.soleModal.renderFlashMessages(ajaxData.flash_messages);
257
+
258
+ if (modalHtml.length) {
259
+ fw.soleModal.show(
260
+ 'fw-options-ajax-save-success',
261
+ '<div style="margin: 0 35px;">' + modalHtml + '</div>',
262
+ {
263
+ autoHide: noErrors
264
+ ? 1000 // hide fast the message if everything went fine
265
+ : 10000,
266
+ showCloseButton: false,
267
+ hidePrevious: noErrors ? false : true // close and open popup when there are errors
268
+ }
269
+ );
270
+ } else {
271
+ fw.soleModal.hide();
272
+ }
273
  } while(false);
274
 
275
  /**
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === Unyson ===
2
  Contributors: unyson
3
- Tags: page builder, 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.4
5
  Tested up to: 4.7
6
- Stable tag: 2.6.10
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -11,6 +11,8 @@ A simple and easy way to build a powerful website.
11
 
12
  == Description ==
13
 
 
 
14
  [Unyson](http://unyson.io/) - A free drag & drop framework that comes with a bunch of built in extensions that will help you develop premium themes fast & easy.
15
 
16
  [Sponsored by: BitBlox.me](http://bitblox.me/)
@@ -83,6 +85,15 @@ Yes; Unyson will work with any theme.
83
 
84
  == Changelog ==
85
 
 
 
 
 
 
 
 
 
 
86
  = 2.6.10 =
87
  * Fixed [#2216](https://github.com/ThemeFuse/Unyson/issues/2216), [#2212](https://github.com/ThemeFuse/Unyson/issues/2212), [#2214](https://github.com/ThemeFuse/Unyson/issues/2214)
88
 
@@ -176,7 +187,6 @@ Yes; Unyson will work with any theme.
176
  * Fixed [#1062](https://github.com/ThemeFuse/Unyson/issues/1062), [#1278](https://github.com/ThemeFuse/Unyson/issues/1278), [#1292](https://github.com/ThemeFuse/Unyson/issues/1292), [#1293](https://github.com/ThemeFuse/Unyson/issues/1293), [#1310](https://github.com/ThemeFuse/Unyson/pull/1310), [#1295](https://github.com/ThemeFuse/Unyson/issues/1295), [#767](https://github.com/ThemeFuse/Unyson/issues/767), [#1322](https://github.com/ThemeFuse/Unyson/pull/1322), [#1323](https://github.com/ThemeFuse/Unyson/pull/1323), [#1321](https://github.com/ThemeFuse/Unyson/issues/1321), [#1054](https://github.com/ThemeFuse/Unyson/issues/1054), [#1309](https://github.com/ThemeFuse/Unyson/issues/1309), [#1347](https://github.com/ThemeFuse/Unyson/issues/1347), [#2777093](https://wordpress.org/support/topic/bootstrap-datepicker-not-translated-on-backend), [#1355](https://github.com/ThemeFuse/Unyson/issues/1355), [#1354](https://github.com/ThemeFuse/Unyson/issues/1354), [#1379](https://github.com/ThemeFuse/Unyson/issues/1379), [#1394](https://github.com/ThemeFuse/Unyson/issues/1394), [#1391](https://github.com/ThemeFuse/Unyson/issues/1391), [#1403](https://github.com/ThemeFuse/Unyson/pull/1403)
177
  * Fixes for [WP 4.5 BackboneJS & UnderscoreJS latest version](https://make.wordpress.org/core/2016/02/17/backbone-and-underscore-updated-to-latest-versions/)
178
 
179
-
180
  = 2.5.0 =
181
  * Added the possibility to save options in separate database location [#838](https://github.com/ThemeFuse/Unyson/issues/838)
182
 
@@ -191,159 +201,3 @@ Yes; Unyson will work with any theme.
191
  * Added the [`.pot` file](https://github.com/ThemeFuse/Unyson/tree/master/framework/languages) [#1256](https://github.com/ThemeFuse/Unyson/issues/1256)
192
 
193
  * Fixed [#1072](https://github.com/ThemeFuse/Unyson/issues/1072), [#1052](https://github.com/ThemeFuse/Unyson/issues/1052), [#1235](https://github.com/ThemeFuse/Unyson/issues/1235), [#1236](https://github.com/ThemeFuse/Unyson/issues/1236), [#1251](https://github.com/ThemeFuse/Unyson/issues/1251), [#1246](https://github.com/ThemeFuse/Unyson/issues/1246), [#1242](https://github.com/ThemeFuse/Unyson/issues/1242), [#941](https://github.com/ThemeFuse/Unyson/issues/941), [#1250](https://github.com/ThemeFuse/Unyson/issues/1250), [#1243](https://github.com/ThemeFuse/Unyson/issues/1243), [#1261](https://github.com/ThemeFuse/Unyson/issues/1261)
194
-
195
- = 2.4.17 =
196
- * Fixed [#1197](https://github.com/ThemeFuse/Unyson/issues/1197)
197
- * Added `'oembed'` option type ([docs](http://manual.unyson.io/en/latest/options/built-in-option-types.html#oembed))
198
- * fixed: `fw_get_db_customizer_option()` infinite recursion when called with default value inside `customizer.php`
199
-
200
- = 2.4.16 =
201
- * Fixed [#1178](https://github.com/ThemeFuse/Unyson/issues/1178), [#1179](https://github.com/ThemeFuse/Unyson/issues/1179), [#1169](https://github.com/ThemeFuse/Unyson/issues/1169), [#1085](https://github.com/ThemeFuse/Unyson/issues/1085)
202
-
203
- = 2.4.15 =
204
- * Fixed [#1164](https://github.com/ThemeFuse/Unyson/issues/1164), [#1080](https://github.com/ThemeFuse/Unyson/issues/1080), [#1006](https://github.com/ThemeFuse/Unyson/issues/1006), [#1139](https://github.com/ThemeFuse/Unyson/pull/1139), [#1152](https://github.com/ThemeFuse/Unyson/pull/1152), [#1157](https://github.com/ThemeFuse/Unyson/pull/1157)
205
-
206
- = 2.4.14 =
207
- * Customizer options: Added `wp-customizer-args` parameter. [#1097](https://github.com/ThemeFuse/Unyson/issues/1097), [#1082](https://github.com/ThemeFuse/Unyson/issues/1082)
208
-
209
- $options = array(
210
- 'b' => array(
211
- 'wp-customizer-args' => array( // <---
212
- 'priority' => 10,
213
- 'active_callback' => 'is_front_page',
214
- ),
215
- 'type' => 'box',
216
- 'options' => array(
217
- 'o' => array('type' => 'text')
218
- )
219
- )
220
- );
221
-
222
- * Option type `switch`: Changed html input value structure. [#1083](https://github.com/ThemeFuse/Unyson/issues/1083)
223
- * Improved the `FW_WP_Filesystem` helper. [#1127](https://github.com/ThemeFuse/Unyson/issues/1127)
224
-
225
- = 2.4.13 =
226
- * **IMPORTANT!!!** Updating from v2.4.12 to any newer version will uninstall all extensions [#1105](https://github.com/ThemeFuse/Unyson/issues/1105#issuecomment-163966468)
227
-
228
- We are very sorry
229
-
230
- To install all extensions compatible with your theme, open the following link:
231
-
232
- ```
233
- {site.domain}/wp-admin/admin.php?page=fw-extensions&sub-page=install&supported
234
- ```
235
-
236
- * Fixed [#1089](https://github.com/ThemeFuse/Unyson/issues/1089), [#1077](https://github.com/ThemeFuse/Unyson/pull/1077#issuecomment-163324948)
237
-
238
- = 2.4.12 =
239
- * WordPress 4.4 fixes
240
- * Fixed
241
- [#1039](https://github.com/ThemeFuse/Unyson/issues/1039),
242
- [#1044](https://github.com/ThemeFuse/Unyson/issues/1044),
243
- [#1055](https://github.com/ThemeFuse/Unyson/pull/1055),
244
- [#1072](https://github.com/ThemeFuse/Unyson/issues/1072),
245
- [#1049](https://github.com/ThemeFuse/Unyson/issues/1049),
246
- [#1086](https://github.com/ThemeFuse/Unyson/issues/1086),
247
- [PageBuilder#40](https://github.com/ThemeFuse/Unyson-PageBuilder-Extension/issues/40#issuecomment-160135453)
248
-
249
- = 2.4.11 =
250
- * Fixed a bug in `popup` option-type: Options were not saved
251
-
252
- = 2.4.10 =
253
- * New extension: [Backup & Demo Content](http://manual.unyson.io/en/latest/extension/backups/#content) *(Note: It will not be visible in extensions list if old Backup extension is set as supported in [theme manifest](http://manual.unyson.io/en/latest/manifest/theme.html#content))*
254
- * Soft removed 3 extensions: Styling, Translation, Learning [#874](https://github.com/ThemeFuse/Unyson/issues/874)
255
- * Added option type `short-slider` (same as `slider`, but it's smaller)
256
- * Fixed html validation error. Added current url in `FW_Form` `<form action="...">`
257
- * Option type `upload`: Added `files_ext` and `extra_mime_types` parameters ([docs](http://manual.unyson.io/en/latest/options/built-in-option-types.html#upload))
258
- * `fw.Modal`: added `headerElements` attribute to set html elements in modal header
259
- * `fw.soleModal`: added `backdrop: null|bool` parameter to set backdrop transparent, white or dark
260
- * Added classes: `FW_Type` and `FW_Type_Register` *(used in the new Backup extension)*
261
- * Fixed [#993](https://github.com/ThemeFuse/Unyson/issues/993)
262
- * RTL fixes
263
- * Other minor fixes ([the diff](https://github.com/ThemeFuse/Unyson/compare/v2.4.9...v2.4.10))
264
-
265
- = 2.4.9 =
266
- * Fixed [#889](https://github.com/ThemeFuse/Unyson/issues/889) Some scripts/styles were enqueued too early
267
- * Minor fixes and improvements ([diff](https://github.com/ThemeFuse/Unyson/compare/v2.4.8...v2.4.9))
268
-
269
- = 2.4.8 =
270
- * Option type `color-picker` and `rgba-color-picker`: Added "Reset" button [#831](https://github.com/ThemeFuse/Unyson/issues/831)
271
- * Fixed [#853](https://github.com/ThemeFuse/Unyson/issues/853), [#856](https://github.com/ThemeFuse/Unyson/issues/856), [#794](https://github.com/ThemeFuse/Unyson/issues/794), [#865](https://github.com/ThemeFuse/Unyson/issues/865), [#873](https://github.com/ThemeFuse/Unyson/issues/873), [#876](https://github.com/ThemeFuse/Unyson/issues/876)
272
- * Unycon v2: Removed strange (not useful) icons
273
-
274
- Demo and search `http://{your-site.com}/wp-content/plugins/unyson/framework/static/libs/unycon/`
275
-
276
- * For extension developers: Now you can set font icon as [thumbnail](http://manual.unyson.io/en/latest/manifest/extension.html)
277
-
278
- ```
279
- $manifest['thumbnail'] = 'fa fa-btc'; // or 'dashicons' or 'unycon'
280
- ```
281
-
282
- * Extensions list: Changed extension buttons *(Install, Activate, Deactive, Remove)* position to make more space for description
283
-
284
- = 2.4.7 =
285
- * FontAwesome 4.4.0
286
- * Improved extension ajax install/uninstall [#809](https://github.com/ThemeFuse/Unyson/issues/809)
287
- * Fixed [#829](https://github.com/ThemeFuse/Unyson/issues/829), [#820](https://github.com/ThemeFuse/Unyson/issues/820), [Shortcodes#31](https://github.com/ThemeFuse/Unyson-Shortcodes-Extension/issues/31)
288
-
289
- = 2.4.6 =
290
- * Fixed: Extensions uninstalled after auto-update [#263](https://github.com/ThemeFuse/Unyson/issues/263)
291
-
292
- = 2.4.5 =
293
- * Fixed [#768](https://github.com/ThemeFuse/Unyson/issues/768)
294
- * Create `ABSPATH .'/fw-update.log'` on plugin update to help solve [#263](https://github.com/ThemeFuse/Unyson/issues/263)
295
-
296
- = 2.4.4 =
297
- * Fixed [#757](https://github.com/ThemeFuse/Unyson/issues/757), [#752](https://github.com/ThemeFuse/Unyson/issues/752#issuecomment-124839194)
298
- * fw.OptionsModal: Prevent Reset button to change the value. It should reset only the form's html
299
- * Minor refactor in code that is responsible for auto-save post options save
300
-
301
- = 2.4.3 =
302
- * [An attempt](https://github.com/ThemeFuse/Unyson/commit/9985875d56520caae4ce72c7111aea1e326777a5) to fix [#263](https://github.com/ThemeFuse/Unyson/issues/263)
303
-
304
- = 2.4.2 =
305
- * Allow containers without the `type` parameter in [Customizer options](http://manual.unyson.io/en/latest/options/introduction.html#customizer)
306
-
307
- = 2.4.1 =
308
- * Fixed [#742](https://github.com/ThemeFuse/Unyson/issues/742), [#731](https://github.com/ThemeFuse/Unyson/issues/731), [#728](https://github.com/ThemeFuse/Unyson/issues/728), [#726](https://github.com/ThemeFuse/Unyson/issues/726), [Shortcodes#29](https://github.com/ThemeFuse/Unyson-Shortcodes-Extension/issues/29)
309
- * Fixed: `addable-popup` option type wasn't saved in Customizer
310
-
311
- = 2.4.0 =
312
- * Created "Container Types" and container type `popup` [#615](https://github.com/ThemeFuse/Unyson/issues/615)
313
- * Created the `fw_collect_options()` function [#740](https://github.com/ThemeFuse/Unyson/issues/740)
314
- * Added Unycon font icon. Demo `http://{your-host}/wp-content/plugins/unyson/framework/static/libs/unycon/demo/`
315
- * Minor fixes
316
-
317
- = 2.3.3 =
318
- * Fixed [#628](https://github.com/ThemeFuse/Unyson/issues/628), [#649](https://github.com/ThemeFuse/Unyson/issues/649), [#637](https://github.com/ThemeFuse/Unyson/issues/637), [#358](https://github.com/ThemeFuse/Unyson/issues/358)
319
- * Added option type `typography-v2`
320
- * Option type `addable-option`, `addable-box` and `addable-popup`: Added the `add-button-text` and `sortable` parameters [#631](https://github.com/ThemeFuse/Unyson/issues/631)
321
- * Optimized option type `typography` fonts select (now it loads faster)
322
- * Extension download improvement: Fetch only [the latest release](https://developer.github.com/v3/repos/releases/#get-the-latest-release) instead of [all releases](https://developer.github.com/v3/repos/releases/#list-releases-for-a-repository)
323
- * Improved the `fw.loading` js helper. Changed the loading image.
324
- * Option type `range-slider`: fixed bug with default value
325
- * Option type `checkbox` and `switch`: Fix boolean values when the option is used in options modal inside other options
326
- * Call `FW_Option_Type::_init()` after the option type has been registered
327
- * `fw.OptionsModal`: Added html cache [#](https://github.com/ThemeFuse/Unyson/issues/675#issuecomment-112555557)
328
- * Added `$old_value` parameter in `'fw_post_options_update'` action
329
- * Added the `fw_get_image_sizes()` function
330
- * Enabled the `colorpicker` and `textcolor` plugins for the `wp-editor` option type
331
- * Option type `background-image` and `multi-picker`: minor css fixes
332
- * Updated `selectize.js` to `0.12.1`
333
-
334
- = 2.3.2 =
335
- * Added option-type `unique` to make possible [this](http://manual.unyson.io/en/latest/extension/shortcodes/index.html#enqueue-shortcode-dynamic-css-in-page-head)
336
- * Added the `fw_get_google_fonts_v2()` function
337
- * Fixed: The newline character in textarea option in Customizer was replaced with `'rn'` string
338
- * Fixed: Post options (meta) lost after Quick Edit
339
- * Option-type `multi-picker`: Allow support for any option type in picker ([docs](http://manual.unyson.io/en/latest/options/built-in-option-types.html#multi-picker-add-support-for-new-option-type-in-picker))
340
-
341
- = 2.3.1 =
342
- * Fixed [#566](https://github.com/ThemeFuse/Unyson/issues/566), [#550](https://github.com/ThemeFuse/Unyson/issues/550)
343
- * Fixed: Options default values not working in Customizer [#410](https://github.com/ThemeFuse/Unyson/issues/410#issuecomment-103343955)
344
-
345
- = 2.3.0 =
346
- * Options can be used in [Customizer](https://codex.wordpress.org/Theme_Customization_API) [#410](https://github.com/ThemeFuse/Unyson/issues/410)
347
- * Fixed [#77](https://github.com/ThemeFuse/Unyson/issues/77)
348
-
349
-
1
  === Unyson ===
2
  Contributors: unyson
3
+ Tags: page builder, shortcodes, backup, seo, breadcrumbs, portfolio, framework
4
  Requires at least: 4.4
5
  Tested up to: 4.7
6
+ Stable tag: 2.6.11
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
11
 
12
  == Description ==
13
 
14
+ > Did you find this plugin helpful? Please consider [leaving a 5-star review](https://wordpress.org/support/plugin/unyson/reviews/).
15
+
16
  [Unyson](http://unyson.io/) - A free drag & drop framework that comes with a bunch of built in extensions that will help you develop premium themes fast & easy.
17
 
18
  [Sponsored by: BitBlox.me](http://bitblox.me/)
85
 
86
  == Changelog ==
87
 
88
+ = 2.6.11 =
89
+ * Fixed [#2198](https://github.com/ThemeFuse/Unyson/issues/2198), [#2216](https://github.com/ThemeFuse/Unyson/issues/2216), [#2219](https://github.com/ThemeFuse/Unyson/issues/2219), [#2234](https://github.com/ThemeFuse/Unyson/issues/2234), [#2254](https://github.com/ThemeFuse/Unyson/issues/2254), [#2264](https://github.com/ThemeFuse/Unyson/issues/2264), [#2265](https://github.com/ThemeFuse/Unyson/issues/2265), [#2273](https://github.com/ThemeFuse/Unyson/issues/2273)
90
+ * Option-type `multi-select` improvements
91
+ * Option-type `multi-picker`: The same options can be used for multiple choices [#2251](https://github.com/ThemeFuse/Unyson/pull/2251)
92
+ * Autoload a lot of classes [#2225](https://github.com/ThemeFuse/Unyson/pull/2225)
93
+ * New [helper function](https://github.com/ThemeFuse/Unyson/commit/e378efd45e4d6b7435ebac5a836a7556c866a920#diff-1a10d08376d32331dbdc651256766d37R1654) `fw_get_path_url()`
94
+ * Deprecated warning for the `save-in-separate-meta` option parameter
95
+ * Deleted `FW_File_Cache` helper
96
+
97
  = 2.6.10 =
98
  * Fixed [#2216](https://github.com/ThemeFuse/Unyson/issues/2216), [#2212](https://github.com/ThemeFuse/Unyson/issues/2212), [#2214](https://github.com/ThemeFuse/Unyson/issues/2214)
99
 
187
  * Fixed [#1062](https://github.com/ThemeFuse/Unyson/issues/1062), [#1278](https://github.com/ThemeFuse/Unyson/issues/1278), [#1292](https://github.com/ThemeFuse/Unyson/issues/1292), [#1293](https://github.com/ThemeFuse/Unyson/issues/1293), [#1310](https://github.com/ThemeFuse/Unyson/pull/1310), [#1295](https://github.com/ThemeFuse/Unyson/issues/1295), [#767](https://github.com/ThemeFuse/Unyson/issues/767), [#1322](https://github.com/ThemeFuse/Unyson/pull/1322), [#1323](https://github.com/ThemeFuse/Unyson/pull/1323), [#1321](https://github.com/ThemeFuse/Unyson/issues/1321), [#1054](https://github.com/ThemeFuse/Unyson/issues/1054), [#1309](https://github.com/ThemeFuse/Unyson/issues/1309), [#1347](https://github.com/ThemeFuse/Unyson/issues/1347), [#2777093](https://wordpress.org/support/topic/bootstrap-datepicker-not-translated-on-backend), [#1355](https://github.com/ThemeFuse/Unyson/issues/1355), [#1354](https://github.com/ThemeFuse/Unyson/issues/1354), [#1379](https://github.com/ThemeFuse/Unyson/issues/1379), [#1394](https://github.com/ThemeFuse/Unyson/issues/1394), [#1391](https://github.com/ThemeFuse/Unyson/issues/1391), [#1403](https://github.com/ThemeFuse/Unyson/pull/1403)
188
  * Fixes for [WP 4.5 BackboneJS & UnderscoreJS latest version](https://make.wordpress.org/core/2016/02/17/backbone-and-underscore-updated-to-latest-versions/)
189
 
 
190
  = 2.5.0 =
191
  * Added the possibility to save options in separate database location [#838](https://github.com/ThemeFuse/Unyson/issues/838)
192
 
201
  * Added the [`.pot` file](https://github.com/ThemeFuse/Unyson/tree/master/framework/languages) [#1256](https://github.com/ThemeFuse/Unyson/issues/1256)
202
 
203
  * Fixed [#1072](https://github.com/ThemeFuse/Unyson/issues/1072), [#1052](https://github.com/ThemeFuse/Unyson/issues/1052), [#1235](https://github.com/ThemeFuse/Unyson/issues/1235), [#1236](https://github.com/ThemeFuse/Unyson/issues/1236), [#1251](https://github.com/ThemeFuse/Unyson/issues/1251), [#1246](https://github.com/ThemeFuse/Unyson/issues/1246), [#1242](https://github.com/ThemeFuse/Unyson/issues/1242), [#941](https://github.com/ThemeFuse/Unyson/issues/941), [#1250](https://github.com/ThemeFuse/Unyson/issues/1250), [#1243](https://github.com/ThemeFuse/Unyson/issues/1243), [#1261](https://github.com/ThemeFuse/Unyson/issues/1261)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
unyson.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Unyson
4
  * Plugin URI: http://unyson.io/
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.6.10
7
  * Author: ThemeFuse
8
  * Author URI: http://themefuse.com
9
  * License: GPL2+
@@ -16,15 +16,6 @@ if (defined('FW')) {
16
  * The plugin was already loaded (maybe as another plugin with different directory name)
17
  */
18
  } else {
19
-
20
- {
21
- /** @internal */
22
- function _filter_fw_framework_plugin_directory_uri() {
23
- return plugin_dir_url( __FILE__ ) . 'framework';
24
- }
25
- add_filter( 'fw_framework_directory_uri', '_filter_fw_framework_plugin_directory_uri' );
26
- }
27
-
28
  require dirname( __FILE__ ) . '/framework/bootstrap.php';
29
 
30
  /**
@@ -33,7 +24,7 @@ if (defined('FW')) {
33
  * Note:
34
  * The framework doesn't know that it's used as a plugin.
35
  * It can be localed in the theme directory or any other directory.
36
- * Only its path and uri is known (specified above)
37
  */
38
  {
39
  /** @internal */
3
  * Plugin Name: Unyson
4
  * Plugin URI: http://unyson.io/
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.6.11
7
  * Author: ThemeFuse
8
  * Author URI: http://themefuse.com
9
  * License: GPL2+
16
  * The plugin was already loaded (maybe as another plugin with different directory name)
17
  */
18
  } else {
 
 
 
 
 
 
 
 
 
19
  require dirname( __FILE__ ) . '/framework/bootstrap.php';
20
 
21
  /**
24
  * Note:
25
  * The framework doesn't know that it's used as a plugin.
26
  * It can be localed in the theme directory or any other directory.
27
+ * Only its path and uri is known
28
  */
29
  {
30
  /** @internal */