WordPress Page Builder – Beaver Builder - Version 2.5.1

Version Description

Download this release

Release Info

Developer pross
Plugin Icon 128x128 WordPress Page Builder – Beaver Builder
Version 2.5.1
Comparing to
See all releases

Code changes from version 2.4.2.5 to 2.5.1

Files changed (56) hide show
  1. changelog.txt +220 -14
  2. classes/class-fl-builder-admin-posts.php +34 -3
  3. classes/class-fl-builder-admin-settings.php +16 -5
  4. classes/class-fl-builder-admin.php +3 -1
  5. classes/class-fl-builder-ajax-layout.php +299 -30
  6. classes/class-fl-builder-ajax.php +3 -2
  7. classes/class-fl-builder-art.php +1 -1
  8. classes/class-fl-builder-auto-suggest.php +2 -2
  9. classes/class-fl-builder-compatibility.php +127 -1
  10. classes/class-fl-builder-css.php +6 -2
  11. classes/class-fl-builder-debug.php +8 -5
  12. classes/class-fl-builder-font-awesome.php +357 -0
  13. classes/class-fl-builder-fonts.php +54 -10
  14. classes/class-fl-builder-history-manager.php +2 -1
  15. classes/class-fl-builder-icons.php +31 -9
  16. classes/class-fl-builder-loader.php +2 -1
  17. classes/class-fl-builder-loop.php +34 -2
  18. classes/class-fl-builder-model.php +134 -48
  19. classes/class-fl-builder-notifications.php +2 -2
  20. classes/class-fl-builder-revisions.php +26 -3
  21. classes/class-fl-builder-service-mailchimp.php +1 -1
  22. classes/class-fl-builder-service-mailjet.php +5 -1
  23. classes/class-fl-builder-service-mailpoet.php +26 -11
  24. classes/class-fl-builder-services.php +9 -4
  25. classes/class-fl-builder-shortcodes.php +16 -0
  26. classes/class-fl-builder-ui-settings-forms.php +24 -1
  27. classes/class-fl-builder-update.php +2 -2
  28. classes/class-fl-builder-usage.php +5 -5
  29. classes/class-fl-builder-utils.php +9 -2
  30. classes/class-fl-builder-wp-blocks-layout.php +22 -15
  31. classes/class-fl-builder-wpcli-command.php +64 -0
  32. classes/class-fl-builder-wpml.php +15 -0
  33. classes/class-fl-builder.php +136 -44
  34. css/animations/slide-in-left.css +4 -0
  35. css/animations/slide-in-right.css +4 -0
  36. css/build/builder.bundle.css +197 -3
  37. css/build/builder.bundle.min.css +1 -1
  38. css/build/vendor-bb-fluid.bundle.css +676 -825
  39. css/build/vendor-bb-fluid.bundle.min.css +1 -1
  40. css/build/wp-editor.bundle.css +10 -1
  41. css/build/wp-editor.bundle.min.css +1 -1
  42. css/editor.css +1 -1
  43. css/fl-builder-layout-medium.css +4 -1
  44. css/fl-builder-layout-responsive.css +6 -0
  45. css/fl-builder-layout.css +10 -11
  46. css/fl-builder-rtl.css +1 -1
  47. css/fl-builder-ui-skin-dark.css +3 -2
  48. css/fl-builder.css +109 -30
  49. css/fl-builder.min.css +1 -1
  50. css/fl-icon-selector.css +3 -5
  51. css/fl-lightbox.css +5 -5
  52. css/fl-slideshow.css +7 -0
  53. css/fl-slideshow.min.css +1 -1
  54. css/jquery.magnificpopup.min.css +1 -1
  55. css/jquery.tiptip.css +1 -1
  56. data/{layout-01-Home-lite.dat → layout-03-Home-lite.dat} +1 -1
changelog.txt CHANGED
@@ -1,21 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <h4>2.4.2.5 - 07/21/2021</h4>
2
  <strong>Hot Fix</strong>
3
  <ul>
4
- <li>Fix responsive editing while inline CSS is enabled</li>
5
- <li>Accordion Module: Fix spacing issue in HTML when collapse is disabled</li>
6
- <li>Subscribe Module: Fix conflict with WooCommerce Mailer Lite</li>
7
- <li>Subscribe Module: Fix integration with Campaign Monitor when using PHP 8</li>
8
- <li>Subscribe Module: Update MailPoet integration for their new API</li>
9
- <li>Fix notice for block preload path when using WP 5.8</li>
10
  </ul>
11
 
12
  <h4>2.4.2.4 - 06/15/2021</h4>
13
  <strong>Hot Fix</strong>
14
  <ul>
15
- <li>Callout Module: Fix link on icon ignoring link target setting</li>
16
- <li>Allow .webp uploads when using WordPress 5.8 which adds support for .webp files</li>
17
- <li>Add plugin data to data collected when opted into Sending Usage Data</li>
18
- <li>Add support for SendinBlue API v3 since v2 will be discontinued at the end of the month</li>
19
  </ul>
20
 
21
  <h4>2.4.2.3 - 05/25/2021</h4>
@@ -24,16 +231,15 @@
24
  <li>Fixed column width resetting to very small/narrow</li>
25
  </ul>
26
 
27
- <h4>2.4.2.2 - 03/01/2021</h4>
28
  <strong>Hot Fix</strong>
29
  <ul>
30
- <li>Fixed photo cropping issue for subdomain multisite users</li>
31
  <li>Fixed update issue with Godaddy booster plugin</li>
32
  <li>Fixed Post Carousel blur issue with Google Chrome</li>
33
- <li>Fixed issue with Google Fonts not loading when applying a template</li>
34
  </ul>
35
 
36
-
37
  <h4>2.4.2.1 - 02/11/2021</h4>
38
  <strong>Hot Fix</strong>
39
  <ul>
1
+ <h4>2.5.1 - 12/9/2021</h4>
2
+ <p><strong>Enhancements</strong></p>
3
+
4
+ <ul>
5
+ <li>Add new shortcode <code>[fl-safe]</code> to wrap code in that is known to break the UI</li>
6
+ <li>Tweak the way we generate our unique node IDs to ensure that they always will be a string</li>
7
+ <li>Add offset option to Row Parallax background image</li>
8
+ <li>Allow user to choose images for different breakpoints when row is set to parallax background</li>
9
+ <li>Add support for Query Monitor to be used while inside the UI</li>
10
+ <li>Contact Form & Subscribe Form Modules: Show any WP_Error detected so it's easier to debug issues</li>
11
+ <li>Update Ace Editor to latest version</li>
12
+ <li>Update FontAwesome to latest version</li>
13
+ <li>Icon Group Module: Make spacing option responsive</li>
14
+ <li>Reduce number of queries for Saved nodes by switching from using <code>get_terms</code> function to <code>get_the_terms</code> since it's cached</li>
15
+ <li>Pricing Table Module: Make Advanced Spacing, Tooltip Icon Size, Feature Icon Size, Box Top Margin and Typography responsive</li>
16
+ <li>Fix conflict with Signify theme when adding media in UI</li>
17
+ <li>Add new filters <code>fl_builder_render_css_row</code> <code>fl_builder_render_css_col</code> <code>fl_builder_render_css_module</code> <code>fl_builder_render_css_module_{$module->slug}</code></li>
18
+ </ul>
19
+
20
+ <p><strong>Bug Fixes</strong></p>
21
+ <ul>
22
+ <li>Fix issue with Slide Right animation</li>
23
+ <li>Fixed Saved nodes not retaining categories when published in BB UI</li>
24
+ <li>Button Group Module: Fix background animation not working</li>
25
+ <li>Video Module: Fixed flash on loading when set to loop</li>
26
+ <li>Accordion Module: Fix "Expand first item" option issue with anchor links</li>
27
+ <li>Content Slider Module: Fix module autoplaying when clicking on the arrows</li>
28
+ <li>Menu Module: Fix no smooth scrolling on mobile and not closing properly after clicking an anchor link</li>
29
+ <li>Button Module: Fix column text color overriding module color</li>
30
+ <li>Subscribe Module: Fix Mailjet integration only showing 10 lists</li>
31
+ <li>Callout Module: Fix issues with rel attribute</li>
32
+ <li>Fix UI being broken when removing some keyboard shortcuts with <code>fl_builder_keyboard_shortcuts</code> hook</li>
33
+ <li>Add select2 text color for UI Dark Mode</li>
34
+ <li>Fix issue with get_excerpt function showing wrong data when using visibility options</li>
35
+ <li>Pricing Table Module: Fix custom icons not working in feature list</li>
36
+ <li>WPML: Fix cache clear issue when switching domains</li>
37
+ <li>Menu Module: Fix missing closing li tags</li>
38
+ <li>Fix fatal error in UI in certain circumstances when plugins add widgets</li>
39
+ <li>Menu Module: Logo option now correctly outputs alt attribute</li>
40
+ <li>Fix fatal error if search enabled in Menu Module but Search module is disabled in settings and <code>is_module_disable_enabled</code>
41
+ is set to true</li>
42
+ </ul>
43
+
44
+
45
+ <h4>2.5.0.3 - 10/19/2021</h4>
46
+ <p><strong>Bug Fixes</strong></p>
47
+ <ul>
48
+ <li>BB Lite: Fix icon picker not working in some setups when jquery-throttle is not enqueued</li>
49
+ </ul>
50
+
51
+ <h4>2.5.0.2 - 10/7/2021</h4>
52
+ <p><strong>Enhancements</strong></p>
53
+ <ul>
54
+ <li>Ignore http/https in URL check to automatically clear cache when URL changes</li>
55
+ <li>Subscribe Module: Update cacert for Infusionsoft and Campaign Monitor</li>
56
+ </ul>
57
+
58
+ <p><strong>Bug Fixes</strong></p>
59
+ <ul>
60
+ <li>Fix templates registered with <code>FLBuilder::register_templates</code> being duplicated in content panel</li>
61
+ <li>Fix fatal error when saving Posts module with custom layout or when BigCommerce is active</li>
62
+ <li>Fix modules not being greyed out until ready after being duplicated in the BB UI</li>
63
+ <li>Fix not being able to import settings to modules with uppercase characters in class name</li>
64
+ <li>Fix some icons in some icon sets not displaying due to a space being added to the class when prefix is missing for that icon</li>
65
+ <li>Menu Module: Fix menu opening and closing when anchor links are used on a hamburger menu</li>
66
+ </ul>
67
+
68
+ <h4>2.5.0.1 - 09/21/2021</h4>
69
+ <p><strong>Enhancements</strong></p>
70
+ <ul>
71
+ <li>Improve updates message to account for different license situations</li>
72
+ <li>Update welcome page image</li>
73
+ <li>Update readme for Lite modules</li>
74
+ <li>Cache Clearing Tool: Improve Pagely cache clear</li>
75
+ </ul>
76
+
77
+ <p><strong>Bug Fixes</strong></p>
78
+ <ul>
79
+ <li>Subscribe Module: Fix error message alignment when Search module included in the layout</li>
80
+ <li>Icon Picker: various FontAwesome fixes including fixing broken domain check in kit settings, compatibility with FontAwesome plugin, AJAX search now respects admin icon settings, and fix kit displaying even if kit displays no icons</li>
81
+ <li>Number Counter Module: Fix preview not updating properly when changing the number</li>
82
+ <li>Code Editor: right click paste options now appears</li>
83
+ <li>Menu Module: Fix flyout menu panel showing after adding a new module</li>
84
+ <li>Global Modules: Fix global modules opening for editing after dropping it on the page to be consistent with Global Rows/Columns behavior</li>
85
+ <li>Cache Clear Tool: fix Pantheon cache clear not working properly</li>
86
+ <li>Fix certain HTML elements being stripped from post_content fl-builder block on publish</li>
87
+ <li>Fix images not being able to be cropped on the demo server</li>
88
+ <li>Menu Module: Fix separators being different sizes when search enabled</li>
89
+ </ul>
90
+
91
+ <h4>2.5 - 08/19/2021</h4>
92
+ <p><strong>New & Major Updates</strong></p>
93
+ <ul>
94
+ <li>Add Outline Panel to easily see the structure of your page and move things around</li>
95
+ <li>Add Duplicate option for BB posts in the WP Admin</li>
96
+ <li>Premium Templates added - 2 new Landing page templates and several content page templates. Some older templates were also removed.</li>
97
+ <li>In WP Admin list for for saved elements, show shortcode and add click to copy to clipboard</li>
98
+ <li>Icon Picker: various enhancements including live search, recently used icons section and compatibility with FontAwesome plugin</li>
99
+ <li>Menu Module: Add responsive dropdown styles and default menu items when no menus exist on the site</li>
100
+ <li>Menu Module: Now has styling options for sub-menu link colors and the responsive toggle, also new option to have a logo in the center of the menu, new option to add search to the menu, and add support for showing WooCommerce cart contents in the menu</li>
101
+ <li>Pricing Table Module: Add toggle for monthly/yearly pricing, add the ability to add icons for each feature, add Typography options, and add option to display a ribbon</li>
102
+ <li>Subscribe Module: Add filter for users to add their own service <code>fl_builder_subscribe_form_services</code></li>
103
+ </ul>
104
+
105
+ <p><strong>Enhancements</strong></p>
106
+ <ul>
107
+ <li>Button Group Module: Add width for the horizontal layout</li>
108
+ <li>Contact Form Module: Labels are now translatable</li>
109
+ <li>Content Slider Module: Make Button Padding Responsive</li>
110
+ <li>Content Slider: Add Background Overlay option for individual slides</li>
111
+ <li>Countdown Module: Add Typography Options</li>
112
+ <li>Countdown Module: Add overall Alignment option</li>
113
+ <li>List Module: Update icon and move List items section to the top of the first tab</li>
114
+ <li>Menu Module: Add support for Menu Module closing when tabbing through the last of the items</li>
115
+ <li>Number Counter Module: Add Typography</li>
116
+ <li>Number Counter: Add option to choose height of bar and not show number with Bar layout as well as add field connection for number</li>
117
+ <li>Post Modules: Make the suggest fields sortable</li>
118
+ <li>Post Carousel Module: Add Typography options</li>
119
+ <li>Post Slider Module: Now has Typography options</li>
120
+ <li>Separator Module: Height and Alignment are now responsive</li>
121
+ <li>Subscribe Module: Mailpoet 3 integration now shows all lists</li>
122
+ <li>Subscribe Module: Add better error handling if no service is selected</li>
123
+ <li>Testimonials Module: Accessibility improvements with navigation</li>
124
+ <li>Post Modules: Make the suggest fields sortable</li>
125
+ <li>Video Module: Add structured data options for contentUrl and embedUrl</li>
126
+ <li>Columns: Now have custom position available for backgrounds</li>
127
+ <li>Columns: Make width field available even for Single Columns</li>
128
+ <li>Add icons for border, border radius, padding, and margin labels</li>
129
+ <li>Add some improvements to the display of the Launch BB area in WP Editor</li>
130
+ <li>Cache Clearing Tool: Improve integration with CloudFlare plugin</li>
131
+ <li>Developers: Post type field now supports multi-select</li>
132
+ <li>Outline Panel: Add filter to disable <code>fl_builder_outline_panel_enabled</code></li>
133
+ <li>Add support for SEOPress</li>
134
+ <li>Update the Welcome page in WP Admin for 2.5 version</li>
135
+ <li>Update internal links to the Knowledge Base</li>
136
+ <li>Remove Google+ Icon from Slideshow Module</li>
137
+ <li>Shift some wp_options to autoload = false</li>
138
+ <li>Update jQuery deprecated code</li>
139
+ <li>Code Editor: Enable word wrap and line numbers by default</li>
140
+ <li>Fix conflict with 3CX Live Chat plugin</li>
141
+ <li>Add Layout Type As Parameter to the <code>FLBuilder::render_content_classes()</code> method</li>
142
+ <li>Try to remove other Duplicate plugin Duplicate links since they are not compatible with BB</li>
143
+ <li>Border Field Type: Add ability to disable parts of the compound field</li>
144
+ <li>Add custom position for column backgrounds as well</li>
145
+ <li>Allow line height to be 0 in Typography settings</li>
146
+ <li>WPCLI Enhancements: <code>wp beaver global list</code> shows list of all options and <code>wp beaver global-update --id=default_heading_selector --value=.fl-post-header</code> updates a single option</li>
147
+ <li>Add new mode to disable history temporarily</li>
148
+ <li>Debug Mode: Only output errors if <code>showerrors</code> parameter is in the URL</li>
149
+ <li>Disable smooth scroll via custom class <code>fl-no-scroll</code></li>
150
+ <li>Automatically clear CSS/JS files when URL changes</li>
151
+ </ul>
152
+
153
+ <p><strong>Bug Fixes</strong></p>
154
+ <ul>
155
+ <li>Make sure content panel icons for modules are all the same size</li>
156
+ <li>Photo Module: Fix fatal error when using PHP8 and border is a string</li>
157
+ <li>Menu Module: Fix flyout menu being visible while builder is active</li>
158
+ <li>Contact Form Module: Fix console notices when multiple modules are present on the same page</li>
159
+ <li>Icon Module: Fix alignment issues when using multiple modules to create a group of icons</li>
160
+ <li>Icon Module: Fix screen reader text being visible when it should not in some cases</li>
161
+ <li>Menu Module: Adjust search placement on vertical layouts</li>
162
+ <li>Text Editor Module: Fix strong/bold tag styling ignored when font weight is set in module</li>
163
+ <li>Fix SVGs used in layout/global CSS</li>
164
+ <li>Fix notices on WP 5.8 Block Widget Screen</li>
165
+ <li>Photo Module: Fix issue with cropping on some hosts</li>
166
+ <li>UI: Fix node visibility icon flashing on hover</li>
167
+ <li>Fixed PHP Notices when Applying a Template</li>
168
+ <li>Fixed responsive editing being glitchy when inline assets is enabled</li>
169
+ <li>Fixed issue where due to custom code the post_id could be set wrong in AJAX</li>
170
+ <li>Callout Module: Fix image set to show on right being off centered vertically when a link is entered</li>
171
+ <li>Content Slider: Fix mobile image alt tag being empty when using slide content layout</li>
172
+ <li>Slideshow Module: Fix tweet button visibility and issues with icon alignment</li>
173
+ <li>Fixed issue with smooth scrolling when clicking on a "Back to Top" link when Themer "Sticky" Header is enabled</li>
174
+ <li>Fix unneeded AJAX call for notifications</li>
175
+ <li>Text Editor Module: Fix bold not working properly with Google Fonts as that version wasn't being enqueued</li>
176
+ <li>Contact Module: Fix Ampersand displaying as entity in From Email</li>
177
+ <li>Content Slider: Fix delay not resetting and fix issues with slides skipping while in transition</li>
178
+ <li>Countdown Module: Fix circle being clipped at certain sizes</li>
179
+ <li>Icon Picker: Fix missing Icon</li>
180
+ <li>Menu Module: Fix issues with preview showing incorrectly until save</li>
181
+ <li>Subscribe Module: Fix conflict with WooCommerce Mailer Lite</li>
182
+ <li>Subscribe Module: Fix issue where users couldn't join multiple Mailer Lite lists & remove trashed lists from List dropdown</li>
183
+ <li>IE 11: Fix visibility issues where items set to hide on screens were showing unexpectedly</li>
184
+ <li>Restricted Editing: Make sure users can still unpin content panel</li>
185
+ <li>Font Settings: Sanitize FontAwesome Pro Kit URL Field to prevent HTML</li>
186
+ <li>Improvements to prevent Google fonts from being enqueued twice in some circumstances with Global elements</li>
187
+ <li>Row/Column BG color need sanitizing</li>
188
+ <li>Fix YouTube row BG videos not working if you choose a start time</li>
189
+ <li>Fix JS errors when editing/saving form items</li>
190
+ <li>Content Slider: Fix JS error if link clicked after mobile layout kicks in and fix some styles shifting when styles re-arranged</li>
191
+ <li>Photo Fields: fix photo field forgetting selected size if you edited alt text and other data and add new filter to select default size <code>fl_builder_default_image_select_size</code></li>
192
+ <li>Posts Module: Fix JS error seen in FireFox</li
193
+ <li>Subscribe Module: Fix MailPoet Integration after they upgraded their API without backwards compatibility</li>
194
+ <li>Fix: Video background not resizing correctly when picked from Media Library</li>
195
+ <li>Fix custom row/col background positions hiding when they shouldn't</li>
196
+ <li>Fix preview not showing on subforms</li>
197
+ <li>Fix debug URL throwing an error if child theme is active with no functions.php</li>
198
+ <li>Fix JS/CSS error when options keys have a non alphanumeric character</li>
199
+ <li>Fix Molle Google Font not working properly</li>
200
+ <li>Fix inconsistent font-family in builder UI</li>
201
+ <li>Widgets: Fix showing no longer exists message if the title is blank</li>
202
+ <li>SEOPress: Fix issue with second post module on the page pagination doesn't work if category slug is removed in SEOPress.</li>
203
+ <li>Revisions now show correct time when Site Timezone changed</li>
204
+ <li>Fixed issue with color pickers in Dark Mode</li>
205
+ <li>Fixed issue with ampersand used in Categories not showing properly in Loop filters section</li>
206
+ </ul>
207
+
208
  <h4>2.4.2.5 - 07/21/2021</h4>
209
  <strong>Hot Fix</strong>
210
  <ul>
211
+ <li>Fix responsive editing while inline CSS is enabled</li>
212
+ <li>Accordion Module: Fix spacing issue in HTML when collapse is disabled</li>
213
+ <li>Subscribe Module: Fix conflict with WooCommerce Mailer Lite</li>
214
+ <li>Subscribe Module: Fix integration with Campaign Monitor when using PHP 8</li>
215
+ <li>Subscribe Module: Update MailPoet integration for their new API</li>
216
+ <li>Fix notice for block preload path when using WP 5.8</li>
217
  </ul>
218
 
219
  <h4>2.4.2.4 - 06/15/2021</h4>
220
  <strong>Hot Fix</strong>
221
  <ul>
222
+ <li>Callout Module: Fix link on icon ignoring link target setting</li>
223
+ <li>Allow .webp uploads when using WordPress 5.8 which adds support for .webp files</li>
224
+ <li>Add plugin data to data collected when opted into Sending Usage Data</li>
225
+ <li>Add support for SendinBlue API v3 since v2 will be discontinued at the end of the month</li>
226
  </ul>
227
 
228
  <h4>2.4.2.3 - 05/25/2021</h4>
231
  <li>Fixed column width resetting to very small/narrow</li>
232
  </ul>
233
 
234
+ <h4>2.4.2.2 - 03/04/2021</h4>
235
  <strong>Hot Fix</strong>
236
  <ul>
237
+ <li>Fixed photo cropping issue for non-subdomain multisite users</li>
238
  <li>Fixed update issue with Godaddy booster plugin</li>
239
  <li>Fixed Post Carousel blur issue with Google Chrome</li>
240
+ <li>Fixed issue with Google Fonts not loading when applying a template<li>
241
  </ul>
242
 
 
243
  <h4>2.4.2.1 - 02/11/2021</h4>
244
  <strong>Hot Fix</strong>
245
  <ul>
classes/class-fl-builder-admin-posts.php CHANGED
@@ -27,6 +27,7 @@ final class FLBuilderAdminPosts {
27
  add_filter( 'page_row_actions', __CLASS__ . '::render_row_actions_link' );
28
  add_filter( 'post_row_actions', __CLASS__ . '::render_row_actions_link' );
29
  add_action( 'pre_get_posts', __CLASS__ . '::sort_builder_enabled' );
 
30
  }
31
 
32
  /**
@@ -333,7 +334,6 @@ final class FLBuilderAdminPosts {
333
  */
334
  static public function render_row_actions_link( $actions = array() ) {
335
  global $post;
336
-
337
  if ( 'trash' != $post->post_status && current_user_can( 'edit_post', $post->ID ) && wp_check_post_lock( $post->ID ) === false ) {
338
 
339
  /**
@@ -343,17 +343,48 @@ final class FLBuilderAdminPosts {
343
  $is_post_editable = (bool) apply_filters( 'fl_builder_is_post_editable', true, $post );
344
  $user_access = FLBuilderUserAccess::current_user_can( 'builder_access' );
345
  $post_types = FLBuilderModel::get_post_types();
346
-
 
 
347
  if ( in_array( $post->post_type, $post_types ) && $is_post_editable && $user_access ) {
348
  $enabled = get_post_meta( $post->ID, '_fl_builder_enabled', true );
349
- $dot = ' <span style="color:' . ( $enabled ? '#6bc373' : '#d9d9d9' ) . '; font-size:18px;">&bull;</span>';
350
  $actions['fl-builder'] = '<a href="' . FLBuilderModel::get_edit_url() . '">' . FLBuilderModel::get_branding() . $dot . '</a>';
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  }
352
  }
353
 
354
  return $actions;
355
  }
356
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
  /**
358
  * Where to redirect this post on save.
359
  *
27
  add_filter( 'page_row_actions', __CLASS__ . '::render_row_actions_link' );
28
  add_filter( 'post_row_actions', __CLASS__ . '::render_row_actions_link' );
29
  add_action( 'pre_get_posts', __CLASS__ . '::sort_builder_enabled' );
30
+ add_action( 'admin_init', __CLASS__ . '::duplicate_layout' );
31
  }
32
 
33
  /**
334
  */
335
  static public function render_row_actions_link( $actions = array() ) {
336
  global $post;
 
337
  if ( 'trash' != $post->post_status && current_user_can( 'edit_post', $post->ID ) && wp_check_post_lock( $post->ID ) === false ) {
338
 
339
  /**
343
  $is_post_editable = (bool) apply_filters( 'fl_builder_is_post_editable', true, $post );
344
  $user_access = FLBuilderUserAccess::current_user_can( 'builder_access' );
345
  $post_types = FLBuilderModel::get_post_types();
346
+ $typeobj = get_post_type_object( $post->post_type );
347
+ $singular_name = ( isset( $_GET['fl-builder-template-type'] ) ) ? ucfirst( $_GET['fl-builder-template-type'] ) : $typeobj->labels->singular_name;
348
+ $singular_name = ( 'Layout' === $singular_name ) ? 'Template' : $singular_name;
349
  if ( in_array( $post->post_type, $post_types ) && $is_post_editable && $user_access ) {
350
  $enabled = get_post_meta( $post->ID, '_fl_builder_enabled', true );
351
+ $dot = '&nbsp;<span style="color:' . ( $enabled ? '#6bc373' : '#d9d9d9' ) . '; font-size:18px;">&bull;</span>';
352
  $actions['fl-builder'] = '<a href="' . FLBuilderModel::get_edit_url() . '">' . FLBuilderModel::get_branding() . $dot . '</a>';
353
+ if ( $enabled ) {
354
+ $url = add_query_arg( array(
355
+ 'post_type' => $post->post_type,
356
+ 'post_id' => $post->ID,
357
+ 'duplicate_layout' => true,
358
+ 'duplicate_nonce' => wp_create_nonce( 'duplicate_nonce' ),
359
+ ), admin_url() );
360
+ /* translators: %s: post type being duplicated */
361
+ $duplicate_text = sprintf( __( 'Duplicate %s', 'fl-builder' ), $singular_name );
362
+ /* translators: %1$s: post type being duplicated: %2$s: Branding name */
363
+ $duplicate_alt = esc_attr( sprintf( __( 'Duplicate %1$s with %2$s', 'fl-builder' ), $singular_name, FLBuilderModel::get_branding() ) );
364
+ $actions['fl-builder-duplicate'] = sprintf( '<a title="%s" href="%s">%s</a>%s', $duplicate_alt, $url, $duplicate_text, $dot );
365
+ }
366
  }
367
  }
368
 
369
  return $actions;
370
  }
371
 
372
+ static public function duplicate_layout() {
373
+ if ( isset( $_GET['duplicate_layout'] ) ) {
374
+ $id = $_GET['post_id'];
375
+ $nonce = $_GET['duplicate_nonce'];
376
+
377
+ if ( wp_verify_nonce( $nonce, 'duplicate_nonce' ) ) {
378
+ $post_id = FLBuilderModel::duplicate_post( $id );
379
+ $url = FLBuilderModel::get_edit_url( $post_id );
380
+ wp_redirect( $url );
381
+ exit;
382
+ } else {
383
+ wp_die( 'Unauthorized' );
384
+ }
385
+ }
386
+ }
387
+
388
  /**
389
  * Where to redirect this post on save.
390
  *
classes/class-fl-builder-admin-settings.php CHANGED
@@ -484,12 +484,23 @@ final class FLBuilderAdminSettings {
484
 
485
  // Enable pro?
486
  $enable_fa_pro = isset( $_POST['fl-enable-fa-pro'] ) ? true : false;
487
- update_option( '_fl_builder_enable_fa_pro', $enable_fa_pro );
488
  do_action( 'fl_builder_fa_pro_save', $enable_fa_pro );
489
  // Update KIT url
490
  $kit_url = isset( $_POST['fl-fa-pro-kit'] ) ? $_POST['fl-fa-pro-kit'] : '';
491
 
492
- update_option( '_fl_builder_kit_fa_pro', $kit_url );
 
 
 
 
 
 
 
 
 
 
 
493
 
494
  // Delete a set?
495
  if ( ! empty( $_POST['fl-delete-icon-set'] ) ) {
@@ -719,7 +730,7 @@ final class FLBuilderAdminSettings {
719
  $options = get_option( '_fl_builder_settings' );
720
  $options->css = $css;
721
  $options->js = $js;
722
- update_option( '_fl_builder_settings', $options );
723
  }
724
  }
725
  }
@@ -798,13 +809,13 @@ final class FLBuilderAdminSettings {
798
  } elseif ( isset( $_POST['fl-beta-nonce'] ) && wp_verify_nonce( $_POST['fl-beta-nonce'], 'beta' ) ) {
799
 
800
  if ( isset( $_POST['beta-checkbox'] ) ) {
801
- update_option( 'fl_beta_updates', true );
802
  } else {
803
  delete_option( 'fl_beta_updates' );
804
  }
805
 
806
  if ( isset( $_POST['alpha-checkbox'] ) ) {
807
- update_option( 'fl_alpha_updates', true );
808
  } else {
809
  delete_option( 'fl_alpha_updates' );
810
  }
484
 
485
  // Enable pro?
486
  $enable_fa_pro = isset( $_POST['fl-enable-fa-pro'] ) ? true : false;
487
+ FLBuilderUtils::update_option( '_fl_builder_enable_fa_pro', $enable_fa_pro );
488
  do_action( 'fl_builder_fa_pro_save', $enable_fa_pro );
489
  // Update KIT url
490
  $kit_url = isset( $_POST['fl-fa-pro-kit'] ) ? $_POST['fl-fa-pro-kit'] : '';
491
 
492
+ preg_match( '#https:\/\/.+\.js#', $kit_url, $match );
493
+
494
+ if ( $kit_url && isset( $match[0] ) ) {
495
+ FLBuilderUtils::update_option( '_fl_builder_kit_fa_pro', $match[0] );
496
+ } else {
497
+ if ( ! $kit_url ) {
498
+ FLBuilderUtils::update_option( '_fl_builder_kit_fa_pro', '' );
499
+ } else {
500
+ /* translators: %s: KIT url */
501
+ self::add_error( sprintf( __( 'Invalid Kit Url: we were unable to determine the URL, code entered was %s', 'fl-builder' ), '<code>' . esc_html( $kit_url ) . '</code>' ) );
502
+ }
503
+ }
504
 
505
  // Delete a set?
506
  if ( ! empty( $_POST['fl-delete-icon-set'] ) ) {
730
  $options = get_option( '_fl_builder_settings' );
731
  $options->css = $css;
732
  $options->js = $js;
733
+ FLBuilderUtils::update_option( '_fl_builder_settings', $options );
734
  }
735
  }
736
  }
809
  } elseif ( isset( $_POST['fl-beta-nonce'] ) && wp_verify_nonce( $_POST['fl-beta-nonce'], 'beta' ) ) {
810
 
811
  if ( isset( $_POST['beta-checkbox'] ) ) {
812
+ FLBuilderUtils::update_option( 'fl_beta_updates', true );
813
  } else {
814
  delete_option( 'fl_beta_updates' );
815
  }
816
 
817
  if ( isset( $_POST['alpha-checkbox'] ) ) {
818
+ FLBuilderUtils::update_option( 'fl_alpha_updates', true );
819
  } else {
820
  delete_option( 'fl_alpha_updates' );
821
  }
classes/class-fl-builder-admin.php CHANGED
@@ -147,6 +147,8 @@ final class FLBuilderAdmin {
147
  sprintf( __( 'Install Error! You appear to have a %s file in your uploads folder that will block all javascript files resulting in 403 errors. If you did not add this file please consult your host.', 'fl-builder' ), '<code>.htaccess</code>' ) );
148
  }
149
  }
 
 
150
  }
151
 
152
  /**
@@ -284,7 +286,7 @@ final class FLBuilderAdmin {
284
 
285
  if ( ! $curl ) {
286
  $text = __( 'We’ve detected that your server does not have the PHP cURL extension installed. Ask your hosting provider to install it so you’ll be able to perform automatic updates without error.', 'fl-builder' );
287
- $link = 'https://kb.wpbeaverbuilder.com/article/740-troubleshooting-error-when-trying-to-install-update';
288
  $link_txt = __( 'See our Knowledge Base for more info.', 'fl-builder' );
289
  printf( '<div class="curl-alert"><p>%s</p><p><a target="_blank" href="%s">%s</a></p></div>', $text, $link, $link_txt );
290
  }
147
  sprintf( __( 'Install Error! You appear to have a %s file in your uploads folder that will block all javascript files resulting in 403 errors. If you did not add this file please consult your host.', 'fl-builder' ), '<code>.htaccess</code>' ) );
148
  }
149
  }
150
+
151
+ do_action( 'fl_builder_after_sanity_checks' );
152
  }
153
 
154
  /**
286
 
287
  if ( ! $curl ) {
288
  $text = __( 'We’ve detected that your server does not have the PHP cURL extension installed. Ask your hosting provider to install it so you’ll be able to perform automatic updates without error.', 'fl-builder' );
289
+ $link = 'https://docs.wpbeaverbuilder.com/beaver-builder/troubleshooting/common-issues/error-when-trying-to-install-update';
290
  $link_txt = __( 'See our Knowledge Base for more info.', 'fl-builder' );
291
  printf( '<div class="curl-alert"><p>%s</p><p><a target="_blank" href="%s">%s</a></p></div>', $text, $link, $link_txt );
292
  }
classes/class-fl-builder-ajax-layout.php CHANGED
@@ -105,12 +105,37 @@ final class FLBuilderAJAXLayout {
105
  */
106
  do_action( 'fl_builder_after_render_ajax_layout_html' );
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  // Return the response.
109
  return array(
110
- 'partial' => true,
111
- 'nodeType' => $row->type,
112
- 'html' => $html,
113
- 'js' => 'FLBuilder._renderLayoutComplete();',
 
 
114
  );
115
  }
116
 
@@ -133,9 +158,34 @@ final class FLBuilderAJAXLayout {
133
  $row = FLBuilderModel::apply_node_template( $template_id, null, $position );
134
  }
135
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  return array(
137
- 'layout' => self::render( $row->node ),
138
- 'config' => FLBuilderUISettingsForms::get_node_js_config(),
 
 
139
  );
140
  }
141
 
@@ -149,9 +199,38 @@ final class FLBuilderAJAXLayout {
149
  * @return array
150
  */
151
  static public function copy_row( $node_id, $settings = null, $settings_id = null ) {
152
- $row = FLBuilderModel::copy_row( $node_id, $settings, $settings_id );
 
153
 
154
- return self::render( $row->node );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  }
156
 
157
  /**
@@ -183,12 +262,37 @@ final class FLBuilderAJAXLayout {
183
  */
184
  do_action( 'fl_builder_after_render_ajax_layout_html' );
185
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  // Return the response.
187
  return array(
188
- 'partial' => true,
189
- 'nodeType' => $group->type,
190
- 'html' => $html,
191
- 'js' => 'FLBuilder._renderLayoutComplete();',
 
 
192
  );
193
  }
194
 
@@ -205,10 +309,21 @@ final class FLBuilderAJAXLayout {
205
  */
206
  static public function render_new_columns( $node_id, $insert, $type, $nested, $module = null ) {
207
  // Add the column(s).
208
- $group = FLBuilderModel::add_cols( $node_id, $insert, $type, $nested, $module );
 
 
 
 
 
 
 
 
 
 
 
209
 
210
  // Return the response.
211
- return self::render( $group->node );
212
  }
213
 
214
  /**
@@ -232,23 +347,52 @@ final class FLBuilderAJAXLayout {
232
  // Get the new column parent.
233
  $parent = ! $parent_id ? null : FLBuilderModel::get_node( $parent_id );
234
 
235
- // Get the node to render.
236
  if ( ! $parent ) {
237
  $row = FLBuilderModel::get_col_parent( 'row', $column );
238
  $render_id = $row->node;
 
239
  } elseif ( 'row' == $parent->type ) {
240
  $group = FLBuilderModel::get_col_parent( 'column-group', $column );
241
  $render_id = $group->node;
 
242
  } elseif ( 'column-group' == $parent->type ) {
243
  $render_id = $parent->node;
 
244
  } else {
245
  $render_id = $column->node;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  }
247
 
248
  // Return the response.
249
  return array(
250
- 'layout' => self::render( $render_id ),
251
- 'config' => FLBuilderUISettingsForms::get_node_js_config(),
 
 
252
  );
253
  }
254
 
@@ -262,9 +406,41 @@ final class FLBuilderAJAXLayout {
262
  * @return array
263
  */
264
  static public function copy_col( $node_id, $settings = null, $settings_id = null ) {
265
- $col = FLBuilderModel::copy_col( $node_id, $settings, $settings_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
 
267
- return self::render( $col->node );
 
 
 
 
 
268
  }
269
 
270
  /**
@@ -316,15 +492,64 @@ final class FLBuilderAJAXLayout {
316
  $render_id = null;
317
  }
318
 
319
- // Return the response.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  return array(
321
- 'type' => $module->settings->type,
322
- 'nodeId' => $module->node,
323
- 'parentId' => $module->parent,
324
- 'global' => FLBuilderModel::is_node_global( $module ),
325
- 'layout' => self::render( $render_id ),
326
- 'settings' => null === $template_id && ! $alias ? null : $module->settings,
327
- 'legacy' => FLBuilderUISettingsForms::pre_render_legacy_module_settings( $module->settings->type, $module->settings ),
 
 
328
  );
329
  }
330
 
@@ -337,9 +562,39 @@ final class FLBuilderAJAXLayout {
337
  * @return array
338
  */
339
  static public function copy_module( $node_id, $settings = null ) {
340
- $module = FLBuilderModel::copy_module( $node_id, $settings );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
 
342
- return self::render( $module->node );
 
 
 
 
 
343
  }
344
 
345
  /**
@@ -503,7 +758,7 @@ final class FLBuilderAJAXLayout {
503
  * Use this filter to prevent the builder from rendering shortcodes.
504
  * It is useful if you don't want shortcodes rendering while the builder UI is active.
505
  * @see fl_builder_render_shortcodes
506
- * @link https://kb.wpbeaverbuilder.com/article/117-plugin-filter-reference
507
  */
508
  if ( apply_filters( 'fl_builder_render_shortcodes', true ) ) {
509
  /**
@@ -694,4 +949,18 @@ final class FLBuilderAJAXLayout {
694
  // Return the scripts and styles markup.
695
  return ob_get_clean();
696
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
697
  }
105
  */
106
  do_action( 'fl_builder_after_render_ajax_layout_html' );
107
 
108
+ /**
109
+ * New Nodes
110
+ *
111
+ * We need whole objects for any newly-created nodes.
112
+ */
113
+ $new_nodes = FLBuilderModel::get_nested_nodes( $row->node );
114
+ $new_nodes[ $row->node ] = $row;
115
+
116
+ /**
117
+ * Get Siblings who's positions have changed.
118
+ * Only need node fragments for this.
119
+ */
120
+ $siblings = FLBuilderModel::get_nodes( 'row' );
121
+ $updated_nodes = array();
122
+ foreach ( $siblings as $sibling ) {
123
+ if ( is_object( $sibling ) && isset( $sibling->node ) && $sibling->node !== $row->node ) {
124
+
125
+ // Sibling position should be the only thing that has changed
126
+ $updated_nodes[ $sibling->node ] = new StdClass();
127
+ $updated_nodes[ $sibling->node ]->position = $sibling->position;
128
+ }
129
+ }
130
+
131
  // Return the response.
132
  return array(
133
+ 'partial' => true,
134
+ 'nodeType' => $row->type,
135
+ 'html' => $html,
136
+ 'js' => 'FLBuilder._renderLayoutComplete();',
137
+ 'newNodes' => $new_nodes,
138
+ 'updatedNodes' => $updated_nodes,
139
  );
140
  }
141
 
158
  $row = FLBuilderModel::apply_node_template( $template_id, null, $position );
159
  }
160
 
161
+ /**
162
+ * New Nodes
163
+ *
164
+ * We need whole objects for any newly-created nodes.
165
+ */
166
+ $new_nodes = FLBuilderModel::get_nested_nodes( $row->node );
167
+ $new_nodes[ $row->node ] = $row;
168
+
169
+ /**
170
+ * Get Siblings who's positions have changed.
171
+ * Only need node fragments for this.
172
+ */
173
+ $siblings = FLBuilderModel::get_nodes( 'row' );
174
+ $updated_nodes = array();
175
+ foreach ( $siblings as $sibling ) {
176
+ if ( is_object( $sibling ) && isset( $sibling->node ) && $sibling->node !== $row->node ) {
177
+
178
+ // Sibling position should be the only thing that has changed
179
+ $updated_nodes[ $sibling->node ] = new StdClass();
180
+ $updated_nodes[ $sibling->node ]->position = $sibling->position;
181
+ }
182
+ }
183
+
184
  return array(
185
+ 'layout' => self::render( $row->node ),
186
+ 'config' => FLBuilderUISettingsForms::get_node_js_config(),
187
+ 'newNodes' => $new_nodes,
188
+ 'updatedNodes' => $updated_nodes,
189
  );
190
  }
191
 
199
  * @return array
200
  */
201
  static public function copy_row( $node_id, $settings = null, $settings_id = null ) {
202
+ $row = FLBuilderModel::copy_row( $node_id, $settings, $settings_id );
203
+ $response = self::render( $row->node );
204
 
205
+ /**
206
+ * New Nodes
207
+ *
208
+ * We need whole objects for any newly-created nodes.
209
+ */
210
+ $new_nodes = FLBuilderModel::get_nested_nodes( $row->node );
211
+ $new_nodes[ $row->node ] = $row;
212
+
213
+ /**
214
+ * Get Siblings who's positions have changed.
215
+ * Only need node fragments for this.
216
+ */
217
+ $siblings = FLBuilderModel::get_nodes( 'row' );
218
+ $updated_nodes = array();
219
+ foreach ( $siblings as $sibling ) {
220
+ if ( is_object( $sibling ) && isset( $sibling->node ) && $sibling->node !== $row->node ) {
221
+
222
+ // Sibling position should be the only thing that has changed
223
+ $updated_nodes[ $sibling->node ] = new StdClass();
224
+ $updated_nodes[ $sibling->node ]->position = $sibling->position;
225
+ }
226
+ }
227
+
228
+ $affected_nodes = array(
229
+ 'newNodes' => $new_nodes,
230
+ 'updatedNodes' => $updated_nodes,
231
+ );
232
+
233
+ return array_merge( $response, $affected_nodes );
234
  }
235
 
236
  /**
262
  */
263
  do_action( 'fl_builder_after_render_ajax_layout_html' );
264
 
265
+ /**
266
+ * New Nodes
267
+ *
268
+ * We need whole objects for any newly-created nodes.
269
+ */
270
+ $new_nodes = FLBuilderModel::get_nested_nodes( $group->node );
271
+ $new_nodes[ $group->node ] = $group;
272
+
273
+ /**
274
+ * Get Siblings who's positions have changed.
275
+ * Only need node fragments for this.
276
+ */
277
+ $siblings = FLBuilderModel::get_nodes( 'column-group', $group->parent );
278
+ $updated_nodes = array();
279
+ foreach ( $siblings as $sibling ) {
280
+ if ( is_object( $sibling ) && isset( $sibling->node ) && $sibling->node !== $group->node ) {
281
+
282
+ // Sibling position should be the only thing that has changed
283
+ $updated_nodes[ $sibling->node ] = new StdClass();
284
+ $updated_nodes[ $sibling->node ]->position = $sibling->position;
285
+ }
286
+ }
287
+
288
  // Return the response.
289
  return array(
290
+ 'partial' => true,
291
+ 'nodeType' => $group->type,
292
+ 'html' => $html,
293
+ 'js' => 'FLBuilder._renderLayoutComplete();',
294
+ 'newNodes' => $new_nodes,
295
+ 'updatedNodes' => $updated_nodes,
296
  );
297
  }
298
 
309
  */
310
  static public function render_new_columns( $node_id, $insert, $type, $nested, $module = null ) {
311
  // Add the column(s).
312
+ $group = FLBuilderModel::add_cols( $node_id, $insert, $type, $nested, $module );
313
+ $response = self::render( $group->node );
314
+
315
+ /**
316
+ * Ideally we'd only ship full nodes for the newly-created columns and only position info for the siblings
317
+ * but its pretty tough to determine the new nodes from just the $group here.
318
+ */
319
+ $new_nodes = FLBuilderModel::get_nested_nodes( $group->node );
320
+
321
+ $affected_nodes = array(
322
+ 'newNodes' => $new_nodes,
323
+ );
324
 
325
  // Return the response.
326
+ return array_merge( $response, $affected_nodes );
327
  }
328
 
329
  /**
347
  // Get the new column parent.
348
  $parent = ! $parent_id ? null : FLBuilderModel::get_node( $parent_id );
349
 
350
+ // Get the root node to render.
351
  if ( ! $parent ) {
352
  $row = FLBuilderModel::get_col_parent( 'row', $column );
353
  $render_id = $row->node;
354
+ $root = $row;
355
  } elseif ( 'row' == $parent->type ) {
356
  $group = FLBuilderModel::get_col_parent( 'column-group', $column );
357
  $render_id = $group->node;
358
+ $root = $group;
359
  } elseif ( 'column-group' == $parent->type ) {
360
  $render_id = $parent->node;
361
+ $root = $column;
362
  } else {
363
  $render_id = $column->node;
364
+ $root = $column;
365
+ }
366
+
367
+ /**
368
+ * New Nodes
369
+ *
370
+ * We need whole objects for any newly-created nodes.
371
+ */
372
+ $new_nodes = FLBuilderModel::get_nested_nodes( $root->node );
373
+ $new_nodes[ $root->node ] = $root;
374
+
375
+ /**
376
+ * Get Siblings who's positions have changed.
377
+ * Only need node fragments for this.
378
+ */
379
+ $siblings = FLBuilderModel::get_nodes( $root->type, $root->parent );
380
+ $updated_nodes = array();
381
+ foreach ( $siblings as $sibling ) {
382
+ if ( is_object( $sibling ) && isset( $sibling->node ) && $sibling->node !== $root->node ) {
383
+
384
+ // Sibling position should be the only thing that has changed
385
+ $updated_nodes[ $sibling->node ] = new StdClass();
386
+ $updated_nodes[ $sibling->node ]->position = $sibling->position;
387
+ }
388
  }
389
 
390
  // Return the response.
391
  return array(
392
+ 'layout' => self::render( $render_id ),
393
+ 'config' => FLBuilderUISettingsForms::get_node_js_config(),
394
+ 'newNodes' => $new_nodes,
395
+ 'updatedNodes' => $updated_nodes,
396
  );
397
  }
398
 
406
  * @return array
407
  */
408
  static public function copy_col( $node_id, $settings = null, $settings_id = null ) {
409
+ $col = FLBuilderModel::copy_col( $node_id, $settings, $settings_id );
410
+ $response = self::render( $col->node );
411
+
412
+ /**
413
+ * New Nodes
414
+ *
415
+ * We need whole objects for any newly-created nodes.
416
+ */
417
+ $new_nodes = FLBuilderModel::get_nested_nodes( $col->node );
418
+ $new_nodes[ $col->node ] = $col;
419
+
420
+ /**
421
+ * Get Siblings who's positions and sizes have changed.
422
+ * Only need node fragments for this.
423
+ */
424
+ $siblings = FLBuilderModel::get_nodes( 'column', $col->parent );
425
+ $updated_nodes = array();
426
+ foreach ( $siblings as $sibling ) {
427
+ if ( is_object( $sibling ) && isset( $sibling->node ) && $sibling->node !== $col->node ) {
428
+
429
+ // Sibling position and size should be the only things that have changed
430
+ $updated_nodes[ $sibling->node ] = new StdClass();
431
+ $updated_nodes[ $sibling->node ]->position = $sibling->position;
432
+ $updated_nodes[ $sibling->node ]->settings = array(
433
+ 'size' => $sibling->settings->size,
434
+ );
435
+ }
436
+ }
437
 
438
+ $affected_nodes = array(
439
+ 'newNodes' => $new_nodes,
440
+ 'updatedNodes' => $updated_nodes,
441
+ );
442
+
443
+ return array_merge( $response, $affected_nodes );
444
  }
445
 
446
  /**
492
  $render_id = null;
493
  }
494
 
495
+ // Get node data for redux store
496
+ if ( $module->partial_refresh ) {
497
+ if ( ! $parent ) {
498
+ $scope = 'new-row';
499
+ $root = FLBuilderModel::get_module_parent( 'row', $module );
500
+ $siblings = FLBuilderModel::get_nodes( 'row' );
501
+ } elseif ( 'row' == $parent->type ) {
502
+ $scope = 'new-column-group';
503
+ $root = FLBuilderModel::get_module_parent( 'column-group', $module );
504
+ $siblings = FLBuilderModel::get_nodes( 'column-group', $root->parent );
505
+ } elseif ( 'column-group' == $parent->type ) {
506
+ $scope = 'new-column';
507
+ $root = FLBuilderModel::get_module_parent( 'column', $module );
508
+ $siblings = FLBuilderModel::get_nodes( 'column', $root->parent );
509
+ } else {
510
+ $scope = 'new-module';
511
+ $root = $module;
512
+ $siblings = FLBuilderModel::get_nodes( 'module', $root->parent );
513
+ }
514
+
515
+ /**
516
+ * New Nodes
517
+ *
518
+ * We need whole nodes for any newly-created nodes.
519
+ * Depending on where the module was dropped, $root is the top-most new node.
520
+ */
521
+ $children = FLBuilderModel::get_nested_nodes( $root->node );
522
+ $new_nodes = array_merge( array( $root->node => $root ), $children );
523
+ $new_nodes = FLBuilderModel::clean_layout_data( $new_nodes );
524
+
525
+ /**
526
+ * Get Siblings who's positions have changed.
527
+ * Only need node fragments for this.
528
+ */
529
+ $updated_nodes = array();
530
+ foreach ( $siblings as $sibling ) {
531
+ if ( is_object( $sibling ) && isset( $sibling->node ) && $sibling->node !== $root->node ) {
532
+
533
+ // Sibling position should be the only thing that has changed
534
+ $updated_nodes[ $sibling->node ] = new StdClass();
535
+ $updated_nodes[ $sibling->node ]->position = $sibling->position;
536
+ }
537
+ }
538
+ } else {
539
+ $new_nodes = FLBuilderModel::get_layout_data();
540
+ $updated_nodes = array();
541
+ }
542
+
543
  return array(
544
+ 'type' => $module->settings->type,
545
+ 'nodeId' => $module->node,
546
+ 'parentId' => $module->parent,
547
+ 'global' => FLBuilderModel::is_node_global( $module ),
548
+ 'layout' => self::render( $render_id ),
549
+ 'settings' => $module->settings,
550
+ 'legacy' => FLBuilderUISettingsForms::pre_render_legacy_module_settings( $module->settings->type, $module->settings ),
551
+ 'newNodes' => $new_nodes,
552
+ 'updatedNodes' => $updated_nodes,
553
  );
554
  }
555
 
562
  * @return array
563
  */
564
  static public function copy_module( $node_id, $settings = null ) {
565
+ $module = FLBuilderModel::copy_module( $node_id, $settings );
566
+ $response = self::render( $module->node );
567
+
568
+ /**
569
+ * New Nodes
570
+ *
571
+ * We need whole nodes for any newly-created nodes.
572
+ * Depending on where the module was dropped, $root is the top-most new node.
573
+ */
574
+ $new_nodes = FLBuilderModel::clean_layout_data( array( $module->node => $module ) );
575
+
576
+ /**
577
+ * Get Siblings who's positions have changed.
578
+ * Only need node fragments for this.
579
+ */
580
+ $siblings = FLBuilderModel::get_nodes( 'module', $module->parent );
581
+ $siblings = FLBuilderModel::clean_layout_data( $siblings );
582
+ $updated_nodes = array();
583
+ foreach ( $siblings as $sibling ) {
584
+ if ( is_object( $sibling ) && isset( $sibling->node ) && $sibling->node !== $module->node ) {
585
+
586
+ // Sibling position should be the only thing that has changed
587
+ $updated_nodes[ $sibling->node ] = new StdClass();
588
+ $updated_nodes[ $sibling->node ]->position = $sibling->position;
589
+ }
590
+ }
591
 
592
+ $affected_nodes = array(
593
+ 'newNodes' => $new_nodes,
594
+ 'updatedNodes' => $updated_nodes,
595
+ );
596
+
597
+ return array_merge( $response, $affected_nodes );
598
  }
599
 
600
  /**
758
  * Use this filter to prevent the builder from rendering shortcodes.
759
  * It is useful if you don't want shortcodes rendering while the builder UI is active.
760
  * @see fl_builder_render_shortcodes
761
+ * @link https://docs.wpbeaverbuilder.com/beaver-builder/developer/tutorials-guides/common-beaver-builder-filter-examples
762
  */
763
  if ( apply_filters( 'fl_builder_render_shortcodes', true ) ) {
764
  /**
949
  // Return the scripts and styles markup.
950
  return ob_get_clean();
951
  }
952
+
953
+ /**
954
+ * Get full layout data
955
+ *
956
+ * @since 2.5
957
+ * @access public
958
+ * @return array
959
+ */
960
+ static public function get_layout() {
961
+ return array(
962
+ 'nodes' => FLBuilderModel::get_layout_data(),
963
+ 'attachments' => array(), // @TODO - where do attachments initially come from???
964
+ );
965
+ }
966
  }
classes/class-fl-builder-ajax.php CHANGED
@@ -108,6 +108,7 @@ final class FLBuilderAJAX {
108
  self::add_action( 'clear_cache', 'FLBuilderModel::delete_all_asset_cache' );
109
 
110
  // FLBuilderAJAXLayout
 
111
  self::add_action( 'render_layout', 'FLBuilderAJAXLayout::render' );
112
  self::add_action( 'render_node', 'FLBuilderAJAXLayout::render', array( 'node_id' ) );
113
  self::add_action( 'render_new_row', 'FLBuilderAJAXLayout::render_new_row', array( 'cols', 'position', 'module' ) );
@@ -222,7 +223,7 @@ final class FLBuilderAJAX {
222
  /**
223
  * Allow developers to hook before the action runs.
224
  * @see fl_ajax_before_
225
- * @link https://kb.wpbeaverbuilder.com/article/116-plugin-action-reference
226
  */
227
  do_action( 'fl_ajax_before_' . $action['action'], $keys_args );
228
 
@@ -235,7 +236,7 @@ final class FLBuilderAJAX {
235
  /**
236
  * Allow developers to hook after the action runs.
237
  * @see fl_ajax_after_
238
- * @link https://kb.wpbeaverbuilder.com/article/116-plugin-action-reference
239
  */
240
  do_action( 'fl_ajax_after_' . $action['action'], $keys_args );
241
 
108
  self::add_action( 'clear_cache', 'FLBuilderModel::delete_all_asset_cache' );
109
 
110
  // FLBuilderAJAXLayout
111
+ self::add_action( 'get_layout', 'FLBuilderAJAXLayout::get_layout' );
112
  self::add_action( 'render_layout', 'FLBuilderAJAXLayout::render' );
113
  self::add_action( 'render_node', 'FLBuilderAJAXLayout::render', array( 'node_id' ) );
114
  self::add_action( 'render_new_row', 'FLBuilderAJAXLayout::render_new_row', array( 'cols', 'position', 'module' ) );
223
  /**
224
  * Allow developers to hook before the action runs.
225
  * @see fl_ajax_before_
226
+ * @link https://docs.wpbeaverbuilder.com/beaver-builder/developer/tutorials-guides/common-beaver-builder-filter-examples
227
  */
228
  do_action( 'fl_ajax_before_' . $action['action'], $keys_args );
229
 
236
  /**
237
  * Allow developers to hook after the action runs.
238
  * @see fl_ajax_after_
239
+ * @link https://docs.wpbeaverbuilder.com/beaver-builder/developer/tutorials-guides/common-beaver-builder-filter-examples
240
  */
241
  do_action( 'fl_ajax_after_' . $action['action'], $keys_args );
242
 
classes/class-fl-builder-art.php CHANGED
@@ -110,7 +110,7 @@ class FLBuilderArt {
110
  /**
111
  * Trigger registration process for external shapes.
112
  * @see fl_register_art
113
- * @link https://kb.wpbeaverbuilder.com/article/687-add-custom-shape-art
114
  */
115
  do_action( 'fl_register_art' );
116
  }
110
  /**
111
  * Trigger registration process for external shapes.
112
  * @see fl_register_art
113
+ * @link https://docs.wpbeaverbuilder.com/beaver-builder/developer/tutorials-guides/add-a-custom-shape-layer/
114
  */
115
  do_action( 'fl_register_art' );
116
  }
classes/class-fl-builder-auto-suggest.php CHANGED
@@ -195,7 +195,7 @@ final class FLBuilderAutoSuggest {
195
 
196
  foreach ( $cats as $cat ) {
197
  $data[] = array(
198
- 'name' => $cat->name,
199
  'value' => $cat->term_id,
200
  );
201
  }
@@ -224,7 +224,7 @@ final class FLBuilderAutoSuggest {
224
 
225
  foreach ( $cats as $cat ) {
226
  $data[] = array(
227
- 'name' => $cat->name,
228
  'value' => $cat->term_id,
229
  );
230
  }
195
 
196
  foreach ( $cats as $cat ) {
197
  $data[] = array(
198
+ 'name' => htmlspecialchars_decode( $cat->name ),
199
  'value' => $cat->term_id,
200
  );
201
  }
224
 
225
  foreach ( $cats as $cat ) {
226
  $data[] = array(
227
+ 'name' => htmlspecialchars_decode( $cat->name ),
228
  'value' => $cat->term_id,
229
  );
230
  }
classes/class-fl-builder-compatibility.php CHANGED
@@ -51,6 +51,10 @@ final class FLBuilderCompatibility {
51
  add_action( 'pre_get_posts', array( __CLASS__, 'fix_tribe_events_hide_from_listings_archive' ) );
52
  add_action( 'fl_builder_menu_module_before_render', array( __CLASS__, 'fix_menu_module_before_render' ) );
53
  add_action( 'fl_builder_menu_module_after_render', array( __CLASS__, 'fix_menu_module_after_render' ) );
 
 
 
 
54
 
55
  // Filters
56
  add_filter( 'fl_builder_is_post_editable', array( __CLASS__, 'bp_pages_support' ), 11, 2 );
@@ -73,11 +77,17 @@ final class FLBuilderCompatibility {
73
  add_filter( 'option_wp-smush-lazy_load', array( __CLASS__, 'fix_smush' ) );
74
  add_filter( 'fl_row_bg_video_wrapper_class', array( __CLASS__, 'fix_twenty_twenty_video' ) );
75
  add_filter( 'fl_builder_loop_rewrite_rules', array( __CLASS__, 'fix_wpseo_category_pagination_rule' ) );
 
76
  add_filter( 'fl_builder_loop_rewrite_rules', array( __CLASS__, 'fix_polylang_pagination_rule' ) );
77
  add_filter( 'fl_builder_loop_query_args', array( __CLASS__, 'fix_tribe_events_hide_from_listings' ) );
78
  add_filter( 'tribe_events_rewrite_rules_custom', array( __CLASS__, 'fix_tribe_events_pagination_rule' ), 10, 3 );
79
  add_filter( 'aioseo_conflicting_shortcodes', array( __CLASS__, 'aioseo_conflicting_shortcodes' ) );
80
  add_filter( 'fl_builder_responsive_ignore', array( __CLASS__, 'fix_real_media_library_lite' ) );
 
 
 
 
 
81
  }
82
 
83
  /**
@@ -160,7 +170,7 @@ final class FLBuilderCompatibility {
160
  */
161
  public static function fa_kit_support() {
162
  $kit_url = FLBuilder::fa5_kit_url();
163
- if ( FLBuilder::fa5_pro_enabled() && '' !== $kit_url ) {
164
  wp_dequeue_style( 'font-awesome' );
165
  wp_dequeue_style( 'font-awesome-5' );
166
  wp_deregister_style( 'font-awesome' );
@@ -861,6 +871,35 @@ final class FLBuilderCompatibility {
861
  return $rewrite_rules;
862
  }
863
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
864
  /**
865
  * Fix pagination compatibility with Polylang pages.
866
  *
@@ -885,6 +924,7 @@ final class FLBuilderCompatibility {
885
 
886
  return $rewrite_rules;
887
  }
 
888
  /**
889
  * Fix compatibility issue Woocommerce Products Filter Add-on
890
  *
@@ -1040,5 +1080,91 @@ final class FLBuilderCompatibility {
1040
  $ignore[] = 'real-media-library-lite';
1041
  return $ignore;
1042
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1043
  }
1044
  FLBuilderCompatibility::init();
51
  add_action( 'pre_get_posts', array( __CLASS__, 'fix_tribe_events_hide_from_listings_archive' ) );
52
  add_action( 'fl_builder_menu_module_before_render', array( __CLASS__, 'fix_menu_module_before_render' ) );
53
  add_action( 'fl_builder_menu_module_after_render', array( __CLASS__, 'fix_menu_module_after_render' ) );
54
+ add_action( 'wp_before_admin_bar_render', array( __CLASS__, 'fix_dulicate_page' ), 11 );
55
+ add_action( 'admin_enqueue_scripts', array( __CLASS__, 'fix_3cx_live_chat' ) );
56
+ add_action( 'rest_api_init', array( __CLASS__, 'fix_rest_content' ) );
57
+ add_action( 'wp_enqueue_scripts', array( __CLASS__, 'fix_signify_theme_media' ), 11 );
58
 
59
  // Filters
60
  add_filter( 'fl_builder_is_post_editable', array( __CLASS__, 'bp_pages_support' ), 11, 2 );
77
  add_filter( 'option_wp-smush-lazy_load', array( __CLASS__, 'fix_smush' ) );
78
  add_filter( 'fl_row_bg_video_wrapper_class', array( __CLASS__, 'fix_twenty_twenty_video' ) );
79
  add_filter( 'fl_builder_loop_rewrite_rules', array( __CLASS__, 'fix_wpseo_category_pagination_rule' ) );
80
+ add_filter( 'fl_builder_loop_rewrite_rules', array( __CLASS__, 'fix_seopress_category_pagination_rule' ) );
81
  add_filter( 'fl_builder_loop_rewrite_rules', array( __CLASS__, 'fix_polylang_pagination_rule' ) );
82
  add_filter( 'fl_builder_loop_query_args', array( __CLASS__, 'fix_tribe_events_hide_from_listings' ) );
83
  add_filter( 'tribe_events_rewrite_rules_custom', array( __CLASS__, 'fix_tribe_events_pagination_rule' ), 10, 3 );
84
  add_filter( 'aioseo_conflicting_shortcodes', array( __CLASS__, 'aioseo_conflicting_shortcodes' ) );
85
  add_filter( 'fl_builder_responsive_ignore', array( __CLASS__, 'fix_real_media_library_lite' ) );
86
+ add_filter( 'duplicate_post_show_link', array( __CLASS__, 'fix_duplicate_post_show_link' ), 10, 2 );
87
+ add_filter( 'fl_builder_photo_crop_path', array( __CLASS__, 'fix_flywheel_crop_path' ), 10, 2 );
88
+ add_filter( 'post_row_actions', array( __CLASS__, 'fix_duplicate_post_admin_link' ), 12, 2 );
89
+ add_filter( 'page_row_actions', array( __CLASS__, 'fix_duplicate_post_admin_link' ), 12, 2 );
90
+ add_filter( 'get_the_excerpt', array( __CLASS__, 'fix_rest_excerpt_filter' ), 10, 2 );
91
  }
92
 
93
  /**
170
  */
171
  public static function fa_kit_support() {
172
  $kit_url = FLBuilder::fa5_kit_url();
173
+ if ( FLBuilder::fa5_pro_enabled() && '' !== $kit_url && ! isset( $_GET['fl_builder'] ) && ! FLBuilderFontAwesome::is_installed() ) {
174
  wp_dequeue_style( 'font-awesome' );
175
  wp_dequeue_style( 'font-awesome-5' );
176
  wp_deregister_style( 'font-awesome' );
871
  return $rewrite_rules;
872
  }
873
 
874
+ /**
875
+ * Fix compatibility issue with SEOPress when category prefix is removed
876
+ * in the settings.
877
+ *
878
+ * @since 2.4
879
+ */
880
+ public static function fix_seopress_category_pagination_rule( $rewrite_rules ) {
881
+ if ( ! function_exists( 'seopress_filter_category_rewrite_rules' ) ) {
882
+ return $rewrite_rules;
883
+ }
884
+
885
+ $seopress_cat_rules = seopress_filter_category_rewrite_rules( array() );
886
+ $flpaged_rules = array();
887
+
888
+ foreach ( $seopress_cat_rules as $regex => $redirect ) {
889
+ if ( strpos( $regex, '/page/' ) !== false ) {
890
+ if ( preg_match( '#\((.*?)\)#', $regex, $matches ) ) {
891
+ $flregex = $matches[0] . '/paged-[0-9]{1,}/([0-9]{1,})/?$';
892
+
893
+ // Adds our custom paged rule.
894
+ $flpaged_rules[ $flregex ] = 'index.php?category_name=$matches[1]&flpaged=$matches[2]';
895
+ }
896
+ }
897
+ }
898
+ $rewrite_rules = array_merge( $flpaged_rules, $rewrite_rules );
899
+
900
+ return $rewrite_rules;
901
+ }
902
+
903
  /**
904
  * Fix pagination compatibility with Polylang pages.
905
  *
924
 
925
  return $rewrite_rules;
926
  }
927
+
928
  /**
929
  * Fix compatibility issue Woocommerce Products Filter Add-on
930
  *
1080
  $ignore[] = 'real-media-library-lite';
1081
  return $ignore;
1082
  }
1083
+
1084
+ /**
1085
+ * Disable Yoast duplicate if BB layout is enabled.
1086
+ * @since 2.5
1087
+ */
1088
+ public static function fix_duplicate_post_show_link( $enabled, $post ) {
1089
+ if ( get_post_meta( $post->ID, '_fl_builder_enabled', true ) ) {
1090
+ return false;
1091
+ }
1092
+ return $enabled;
1093
+ }
1094
+
1095
+ /**
1096
+ * Disable duplicate page plugin link in adminbar for BB layouts
1097
+ * @since 2.5
1098
+ */
1099
+ public static function fix_dulicate_page() {
1100
+ global $wp_admin_bar, $post;
1101
+ if ( ! is_admin() && $post instanceof WP_Post && get_post_meta( $post->ID, '_fl_builder_enabled', true ) ) {
1102
+ $wp_admin_bar->remove_node( 'duplicate_this' );
1103
+ }
1104
+ }
1105
+ /**
1106
+ * Disable duplicate page plugin link in admin pages list for BB layouts
1107
+ * @since 2.5
1108
+ */
1109
+ public static function fix_duplicate_post_admin_link( $actions, $post ) {
1110
+ if ( get_post_meta( $post->ID, '_fl_builder_enabled', true ) ) {
1111
+ if ( isset( $actions['duplicate'] ) ) {
1112
+ unset( $actions['duplicate'] );
1113
+ }
1114
+ if ( isset( $actions['duplicate_post'] ) ) {
1115
+ unset( $actions['duplicate_post'] );
1116
+ }
1117
+ }
1118
+ return $actions;
1119
+ }
1120
+
1121
+ /**
1122
+ * @since 2.5
1123
+ */
1124
+ public static function fix_3cx_live_chat() {
1125
+ if ( class_exists( 'TCXSettings' ) && isset( $_GET['page'] ) && 'fl-builder-add-new' == $_GET['page'] ) {
1126
+ remove_action( 'admin_enqueue_scripts', 'wplc_initiate_admin_js', 11 );
1127
+ }
1128
+ }
1129
+
1130
+ /**
1131
+ * @since 2.5
1132
+ */
1133
+ public static function fix_flywheel_crop_path( $url_path, $original ) {
1134
+ if ( defined( 'FLYWHEEL_CONFIG_DIR' ) ) {
1135
+ return trailingslashit( WP_CONTENT_DIR ) . ltrim( str_replace( basename( WP_CONTENT_DIR ), '', wp_make_link_relative( $original ) ), '/' );
1136
+ }
1137
+ return $url_path;
1138
+ }
1139
+
1140
+ /**
1141
+ * When in Rest, if its a BB layout use that data of wp_content
1142
+ */
1143
+ public static function fix_rest_content() {
1144
+ global $render_content_forced;
1145
+ $render_content_forced = true;
1146
+ add_filter( 'get_the_excerpt', 'FLBuilderCompatibility::fix_rest_excerpt_filter', 10, 2 );
1147
+ add_filter( 'the_content', 'FLBuilder::render_content' );
1148
+ }
1149
+
1150
+ public static function fix_rest_excerpt_filter( $excerpt, $post ) {
1151
+ if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
1152
+ remove_filter( 'get_the_excerpt', 'FLBuilderCompatibility::fix_rest_excerpt_filter' );
1153
+ return FLBuilderLoop::get_the_excerpt( $post->ID );
1154
+ }
1155
+ return $excerpt;
1156
+ }
1157
+
1158
+ /**
1159
+ * Fix compatibility issue with Signify Theme
1160
+ *
1161
+ * @since 2.5.1
1162
+ */
1163
+ public static function fix_signify_theme_media() {
1164
+ if ( function_exists( 'signify_setup' )
1165
+ && ( FLBuilderModel::is_builder_active() ) ) {
1166
+ wp_enqueue_style( 'wp-mediaelement', includes_url( '/js/mediaelement/wp-mediaelement.min.css' ) );
1167
+ }
1168
+ }
1169
  }
1170
  FLBuilderCompatibility::init();
classes/class-fl-builder-css.php CHANGED
@@ -307,7 +307,7 @@ final class FLBuilderCSS {
307
  $props['font-size'] = $setting['font_size']['length'] . $setting['font_size']['unit'];
308
  }
309
  }
310
- if ( isset( $setting['line_height'] ) && ! empty( $setting['line_height']['length'] ) ) {
311
  $props['line-height'] = $setting['line_height']['length'];
312
  if ( isset( $setting['line_height']['unit'] ) && ! empty( $setting['line_height']['unit'] ) ) {
313
  $props['line-height'] .= $setting['line_height']['unit'];
@@ -453,8 +453,12 @@ final class FLBuilderCSS {
453
  case 'color':
454
  if ( strstr( $value, 'rgb' ) || strstr( $value, 'url' ) ) {
455
  $css .= "\t$name: $value;\n";
 
 
 
 
456
  } else {
457
- $css .= "\t$name: #$value;\n";
458
  if ( isset( $args['opacity'] ) && '' !== $args['opacity'] ) {
459
  $rgb = implode( ',', FLBuilderColor::hex_to_rgb( $value ) );
460
  $a = $args['opacity'] / 100;
307
  $props['font-size'] = $setting['font_size']['length'] . $setting['font_size']['unit'];
308
  }
309
  }
310
+ if ( isset( $setting['line_height'] ) && ! empty( $setting['line_height']['length'] ) && is_numeric( $setting['line_height']['length'] ) ) {
311
  $props['line-height'] = $setting['line_height']['length'];
312
  if ( isset( $setting['line_height']['unit'] ) && ! empty( $setting['line_height']['unit'] ) ) {
313
  $props['line-height'] .= $setting['line_height']['unit'];
453
  case 'color':
454
  if ( strstr( $value, 'rgb' ) || strstr( $value, 'url' ) ) {
455
  $css .= "\t$name: $value;\n";
456
+ } elseif ( 'inherit' === $value ) {
457
+ $css .= "\t$name: inherit;\n";
458
+ } elseif ( 'transparent' === $value ) {
459
+ $css .= "\t$name: transparent;\n";
460
  } else {
461
+ $css .= sprintf( "\t%s: #%s;\n", $name, ltrim( $value, '#' ) );
462
  if ( isset( $args['opacity'] ) && '' !== $args['opacity'] ) {
463
  $rgb = implode( ',', FLBuilderColor::hex_to_rgb( $value ) );
464
  $a = $args['opacity'] / 100;
classes/class-fl-builder-debug.php CHANGED
@@ -21,9 +21,11 @@ final class FL_Debug {
21
 
22
 
23
  public static function enable_logging() {
24
- @ini_set( 'display_errors', 1 ); // @codingStandardsIgnoreLine
25
- @ini_set( 'display_startup_errors', 1 ); // @codingStandardsIgnoreLine
26
- @error_reporting( E_ALL ); // @codingStandardsIgnoreLine
 
 
27
  }
28
 
29
  public static function display_tests() {
@@ -251,8 +253,9 @@ final class FL_Debug {
251
  // child theme functions
252
  if ( $theme->get( 'Template' ) ) {
253
  $functions_file = trailingslashit( get_stylesheet_directory() ) . 'functions.php';
254
- $contents = file_get_contents( $functions_file );
255
- $args = array(
 
256
  'name' => 'Child Theme Functions',
257
  'data' => $contents,
258
  );
21
 
22
 
23
  public static function enable_logging() {
24
+ if ( isset( $_GET['showerrors'] ) ) {
25
+ @ini_set( 'display_errors', 1 ); // @codingStandardsIgnoreLine
26
+ @ini_set( 'display_startup_errors', 1 ); // @codingStandardsIgnoreLine
27
+ @error_reporting( E_ALL ); // @codingStandardsIgnoreLine
28
+ }
29
  }
30
 
31
  public static function display_tests() {
253
  // child theme functions
254
  if ( $theme->get( 'Template' ) ) {
255
  $functions_file = trailingslashit( get_stylesheet_directory() ) . 'functions.php';
256
+ $contents = file_exists( $functions_file ) ? file_get_contents( $functions_file ) : 'No functions.php found.';
257
+
258
+ $args = array(
259
  'name' => 'Child Theme Functions',
260
  'data' => $contents,
261
  );
classes/class-fl-builder-font-awesome.php ADDED
@@ -0,0 +1,357 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Font Awesome Support Class
4
+ *
5
+ * @since 2.4
6
+ */
7
+
8
+ use function FortAwesome\fa;
9
+
10
+ final class FLBuilderFontAwesome {
11
+
12
+ static $cache_slug = '_fl_builder_font_awesome_data';
13
+ /**
14
+ * @since 2.4
15
+ * @return void
16
+ */
17
+ static public function init() {
18
+ add_action( 'font_awesome_preferences', array( __CLASS__, 'register_plugin' ) );
19
+ add_action( 'wp_enqueue_scripts', array( __CLASS__, 'fa_official_support' ), 999999 );
20
+ add_action( 'fl_builder_after_sanity_checks', array( __CLASS__, 'sanity_checks' ) );
21
+ add_filter( 'fl_builder_ui_js_config', array( __CLASS__, 'js_config' ) );
22
+ add_filter( 'fl_enable_fa5_pro', array( __CLASS__, 'is_pro_enabled' ) );
23
+ FLBuilderAJAX::add_action( 'query_icons', __CLASS__ . '::query_icons', array( 'text' ) );
24
+ FLBuilderAJAX::add_action( 'recent_icons', __CLASS__ . '::recent_icons', array( 'icon' ) );
25
+ }
26
+
27
+ public static function recent_icons( $icon ) {
28
+ $icons = get_option( 'fl_plugin_recent_icons', array() );
29
+ $icons[] = $icon;
30
+ $icons = array_reverse( array_unique( $icons ) );
31
+ update_option( 'fl_plugin_recent_icons', $icons );
32
+ echo json_encode( $icons );
33
+ exit;
34
+ }
35
+
36
+ public static function query_icons( $text ) {
37
+ if ( '' === $text || ! $text ) {
38
+ return '{}';
39
+ }
40
+ $output = array();
41
+ $icons = array();
42
+ $icon_sets = FLBuilderIcons::get_sets();
43
+ $enabled = FLBuilderModel::get_enabled_icons();
44
+ $styles = array();
45
+
46
+ foreach ( (array) $enabled as $set ) {
47
+ switch ( $set ) {
48
+ case 'font-awesome-5-solid':
49
+ $styles[] = 'solid';
50
+ break;
51
+ case 'font-awesome-5-regular':
52
+ $styles[] = 'regular';
53
+ break;
54
+ case 'font-awesome-5-light':
55
+ $styles[] = 'light';
56
+ break;
57
+ case 'font-awesome-5-brands':
58
+ $styles[] = 'brands';
59
+ break;
60
+ case 'font-awesome-5-duotone':
61
+ $styles[] = 'duotone';
62
+ break;
63
+ }
64
+ }
65
+
66
+ if ( self::is_installed() ) {
67
+ $version = fa()->version();
68
+ $membership = ( fa()->pro() ) ? '' : ',membership{free}';
69
+
70
+ $query = sprintf( '{search(version: "%s", query: "%s") { id,label,styles%s }}', fa()->version(), $text, $membership );
71
+
72
+ $result = json_decode( fa()->query( $query ) );
73
+
74
+ if ( isset( $result->data ) && isset( $result->data->search ) ) {
75
+ foreach ( (array) $result->data->search as $icon ) {
76
+ if ( ! fa()->pro() ) {
77
+ if ( empty( $icon->membership->free ) ) {
78
+ continue;
79
+ } else {
80
+ $icon->styles = $icon->membership->free;
81
+ }
82
+ }
83
+ foreach ( $icon->styles as $k => $style ) {
84
+ if ( ! in_array( $style, $styles ) ) {
85
+ unset( $icon->styles[ $k ] );
86
+ }
87
+ }
88
+ $icons[] = array(
89
+ 'tag' => 'fa-' . $icon->id,
90
+ 'label' => $icon->label,
91
+ 'styles' => $icon->styles,
92
+ );
93
+ }
94
+ }
95
+ if ( count( $icons ) > 0 ) {
96
+ $output[] = array(
97
+ 'name' => 'Font Awesome',
98
+ 'slug' => 'font-awesome',
99
+ 'data' => $icons,
100
+ );
101
+ }
102
+ unset( $icon_sets['font-awesome-5-solid'] );
103
+ unset( $icon_sets['font-awesome-5-regular'] );
104
+ unset( $icon_sets['font-awesome-5-brands'] );
105
+ unset( $icon_sets['font-awesome-5-light'] );
106
+ unset( $icon_sets['font-awesome-5-duotone'] );
107
+ }
108
+
109
+ if ( ! in_array( 'font-awesome-kit', $enabled ) ) {
110
+ unset( $icon_sets['font-awesome-kit'] );
111
+ }
112
+
113
+ foreach ( $icon_sets as $set ) {
114
+
115
+ $icons = array();
116
+ foreach ( $set['icons'] as $icon ) {
117
+ if ( strstr( $icon, $text ) ) {
118
+ $icons[] = array(
119
+ 'tag' => $icon,
120
+ 'label' => $icon,
121
+ 'styles' => array( 'legacy' ),
122
+ );
123
+ }
124
+ }
125
+ if ( ! empty( $icons ) ) {
126
+ $output[] = array(
127
+ 'name' => $set['name'],
128
+ 'prefix' => $set['prefix'],
129
+ 'slug' => '',
130
+ 'data' => $icons,
131
+ );
132
+ }
133
+ }
134
+ echo json_encode( $output );
135
+ exit;
136
+ }
137
+
138
+ /**
139
+ * Register this plugin for official FA support.
140
+ */
141
+ public static function register_plugin() {
142
+ $args = apply_filters( 'fl_builder_font_awesome_register_args', array(
143
+ 'name' => __( 'Beaver Builder', 'fl-builder' ),
144
+ 'v4Compat' => false,
145
+ 'technology' => 'webfont',
146
+ ) );
147
+ fa()->register( $args );
148
+ }
149
+
150
+ /**
151
+ * Basic check show warning on BB admin settings.
152
+ */
153
+ public static function sanity_checks() {
154
+
155
+ if ( self::is_installed() && 'svg' === fa()->technology() ) {
156
+ FLBuilderAdminSettings::add_error( self::error_text() );
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Filter our main JS config set fontAwesome var
162
+ */
163
+ public static function js_config( $config ) {
164
+ $config['fontAwesome'] = self::is_installed() ? fa()->technology() : '';
165
+ return $config;
166
+ }
167
+
168
+ /**
169
+ * Dequeue our FA scripts/styles if enqueued
170
+ * @since 2.4
171
+ */
172
+ public static function fa_official_support() {
173
+
174
+ /*
175
+ When BB UI is open:
176
+ If there is no custom kit, or its disabled load regular css.
177
+
178
+ If there is a kit and its enabled:
179
+ if it has icons we need to load the JS
180
+ */
181
+ $kit_enabled = false;
182
+ $enabled = FLBuilderModel::get_enabled_icons();
183
+
184
+ if ( in_array( 'font-awesome-kit', $enabled ) ) {
185
+ $kit_enabled = true;
186
+ }
187
+
188
+ if ( self::is_installed() && ( wp_script_is( 'font-awesome-official', 'enqueued' ) || wp_style_is( 'font-awesome-official', 'enqueued' ) ) ) {
189
+
190
+ // not in builder we can just dequeue the normal css and get out.
191
+ if ( ! isset( $_GET['fl_builder'] ) ) {
192
+ wp_dequeue_style( 'font-awesome' );
193
+ wp_dequeue_style( 'font-awesome-5' );
194
+ wp_deregister_style( 'font-awesome' );
195
+ wp_deregister_style( 'font-awesome-5' );
196
+ }
197
+ // If there is no custom kit, or its disabled load regular css.
198
+ if ( isset( $_GET['fl_builder'] ) ) {
199
+ if ( ! $kit_enabled ) {
200
+ wp_dequeue_script( 'font-awesome-official' );
201
+ wp_dequeue_style( 'font-awesome-official' );
202
+ } else {
203
+ // we have a kit, we need the js so we need to dequeue the css.
204
+ wp_dequeue_style( 'font-awesome' );
205
+ wp_dequeue_style( 'font-awesome-5' );
206
+ wp_deregister_style( 'font-awesome' );
207
+ wp_deregister_style( 'font-awesome-5' );
208
+ }
209
+ }
210
+ }
211
+ }
212
+
213
+ public static function is_pro_enabled( $enabled ) {
214
+
215
+ if ( ! function_exists( 'FortAwesome\fa' ) ) {
216
+ return $enabled;
217
+ }
218
+ if ( self::is_installed() && fa()->pro() ) {
219
+ return true;
220
+ }
221
+
222
+ return $enabled;
223
+ }
224
+
225
+ /**
226
+ * Check if font awesome plugin is available.
227
+ */
228
+ public static function is_installed() {
229
+ return class_exists( 'FortAwesome\FontAwesome_Loader' ) && function_exists( 'FortAwesome\fa' );
230
+ }
231
+
232
+ /**
233
+ * Error text used in wp-admin and modal popup in buildef UI
234
+ */
235
+ public static function error_text() {
236
+ return __( 'You appear to have the font awesome plugin configured to use svg icons, this currently is incompatible with Beaver Builder. You must switch to a webfont set/kit.', 'fl-builder' );
237
+ }
238
+
239
+ /**
240
+ * Latest supported version.
241
+ */
242
+ public static function latest_supported() {
243
+ return '5.15.4';
244
+ }
245
+
246
+ public static function get_kit_icons() {
247
+ $icons = array();
248
+ $result = self::get_kit_data();
249
+
250
+ if ( ! $result ) {
251
+ return array();
252
+ }
253
+
254
+