WordPress Page Builder – Beaver Builder - Version 1.10.4

Version Description

Download this release

Release Info

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

Code changes from version 1.9.5.3 to 1.10.4

Files changed (52) hide show
  1. changelog.txt +128 -0
  2. classes/class-fl-builder-admin-posts.php +10 -5
  3. classes/class-fl-builder-admin-settings.php +22 -28
  4. classes/class-fl-builder-admin.php +4 -1
  5. classes/class-fl-builder-ajax-layout.php +26 -7
  6. classes/class-fl-builder-ajax.php +1 -1
  7. classes/class-fl-builder-auto-suggest.php +68 -46
  8. classes/class-fl-builder-color.php +5 -2
  9. classes/class-fl-builder-export.php +3 -2
  10. classes/class-fl-builder-extensions.php +4 -2
  11. classes/class-fl-builder-fonts.php +121 -3
  12. classes/class-fl-builder-importer.php +14 -6
  13. classes/class-fl-builder-loader.php +25 -24
  14. classes/class-fl-builder-loop.php +124 -14
  15. classes/class-fl-builder-model.php +755 -544
  16. classes/class-fl-builder-service-activecampaign.php +1 -1
  17. classes/class-fl-builder-service-aweber.php +1 -1
  18. classes/class-fl-builder-service-campayn.php +3 -3
  19. classes/class-fl-builder-service-constant-contact.php +4 -4
  20. classes/class-fl-builder-service-enormail.php +233 -0
  21. classes/class-fl-builder-service-getresponse.php +21 -1
  22. classes/class-fl-builder-service-icontact.php +3 -3
  23. classes/class-fl-builder-service-mailerlite.php +0 -1
  24. classes/class-fl-builder-service-mailpoet.php +60 -17
  25. classes/class-fl-builder-service-mailrelay.php +58 -58
  26. classes/class-fl-builder-services.php +88 -77
  27. classes/class-fl-builder-timezones.php +10 -3
  28. classes/class-fl-builder-update.php +165 -28
  29. classes/class-fl-builder-user-access.php +301 -0
  30. classes/class-fl-builder.php +428 -300
  31. classes/class-fl-jsmin.php +2 -3
  32. css/fl-builder-admin-posts-legacy.css +1 -1
  33. css/fl-builder-admin-posts.css +1 -1
  34. css/fl-builder-admin-settings.css +135 -33
  35. css/fl-builder-layout-responsive.css +7 -0
  36. css/fl-builder-layout.css +35 -3
  37. css/fl-builder.css +107 -45
  38. css/fl-builder.min.css +1 -1
  39. css/fl-color-picker.css +18 -15
  40. css/jquery.multiselect.css +120 -0
  41. data/00-Blank.dat +1 -0
  42. data/01-Zen-Life.dat +21 -0
  43. data/02-Janelle-Awkward.dat +9 -0
  44. data/03-Lets-Meat.dat +83 -0
  45. data/04-Moon-Landing.dat +17 -0
  46. data/05-Agency.dat +30 -0
  47. data/06-Royal-Academy.dat +24 -0
  48. data/07-Fashion-Freaks.dat +11 -0
  49. data/08-Procraz.dat +1 -0
  50. data/09-Fullscreen.dat +7 -0
  51. data/10-Wooden.dat +12 -0
  52. data/11-Acme-Tools.dat +1 -0
changelog.txt CHANGED
@@ -1,3 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <h4>1.9.5.3 - 4/4/2017</h4>
2
  <p><strong>Bug Fixes</strong></p>
3
  <ul>
@@ -1751,3 +1878,4 @@
1751
 
1752
  <h4>0.8.1</h4>
1753
  <p>Initial beta release.</p>
 
1
+ <h4>1.10.4 - 5/18/2017</h4>
2
+ <p><strong>Bug Fixes</strong></p>
3
+ <ul>
4
+ <li>Fixed the builder admin menu not showing up for some people with Beaver Themer installed.</li>
5
+ </ul>
6
+
7
+ <h4>1.10.3 - 5/17/2017</h4>
8
+ <p><strong>Enhancements</strong></p>
9
+ <ul>
10
+ <li>Added 'bottom' as an alignment option for row contents.</li>
11
+ <li>Testimonials Module, new setting added to control slider direction.</li>
12
+ <li>Subscribe module MailPoet 3 beta support added.</li>
13
+ <li>Updated pt_PT translation.</li>
14
+ <li>Added the same <a href="http://kb.wpbeaverbuilder.com/article/139-set-up-a-mega-menu" target="_blank">mega menu logic as the theme</a> to the Menu module.</li>
15
+ <li>Added a submenu spacing setting to the Menu module.</li>
16
+ </ul>
17
+ <p><strong>Bug Fixes</strong></p>
18
+ <ul>
19
+ <li>Fixed the column width for reversed stacking order on mobile.</li>
20
+ <li>Fixed a translation error in wp-admin. 'This is a global %s' was not being parsed.</li>
21
+ <li>Fixed RTL issue with testimonials module.</li>
22
+ <li>Fixed a js error if breakpoint was left blank in global settings. Now a required numeric field.</li>
23
+ <li>Fixed an issue where it was possible to have two versions of the plugin active on GoDaddy.</li>
24
+ <li>Fixed an issue with mobile menu flashing unstyled content on initial load.</li>
25
+ <li>Fixed reCaptcha errors in Subscribe & Contact Form Modules.</li>
26
+ <li>Fixed vertical alignment center on full height rows in IE11.</li>
27
+ <li>Fixed an issue with BuddyPress. Builder activate link removed from BuddyPress generated pages.</li>
28
+ <li>Fixed a padding issue on reverse stacked video module.</li>
29
+ <li>Fixed Subscribe Module, GetRespone API would throw an error and not subscribe if name field is hidden.</li>
30
+ <li>Fixed a translation compatibility issue with Beaver Themer plugin.</li>
31
+ <li>Fixed read more link in the Posts module not going below the content and causing line-height issues in the list layout.</li>
32
+ <li>Fixed color picker closing when the mouse goes outside of the picker during drag.</li>
33
+ <li>Fixed hidden global row and module labels when they have long titles.</li>
34
+ </ul>
35
+
36
+ <h4>1.10.2 - 5/2/2017</h4>
37
+ <p><strong>Enhancements</strong></p>
38
+ <ul>
39
+ <li>Added dot indicating whether the builder is enabled or not on builder launch links.</li>
40
+ <li>Added field connections for row background videos.</li>
41
+ <li>Added tinyPNG compatibility for images stored in the builder's cache folder.</li>
42
+ </ul>
43
+ <p><strong>Bug Fixes</strong></p>
44
+ <ul>
45
+ <li>Fixed memory exhausted fatal error when loading templates on servers without enough memory.</li>
46
+ <li>Fixed comments showing in the Posts module when they should not.</li>
47
+ <li>Fixed Posts module pagination when WPML's URL variable is set to lang= rather than directories.</li>
48
+ <li>Fixed JS error in the Posts module when switching from the gallery layout.</li>
49
+ <li>Fixed JetPack sharing icons not showing in the Posts module.</li>
50
+ <li>Fixed line height issue with the Map module.</li>
51
+ <li>Fixed editing templates in the Beaver Builder theme not going full width.</li>
52
+ <li>Fixed some module assets not being re-rendered when working in the builder.</li>
53
+ <li>Fixed issues with preview refresh and responsive editing.</li>
54
+ <li>Fixed subscription check if the site has no internet access and cannot check the subscription state.</li>
55
+ <li>Fixed PHP warning when rendering CSS/JS assets.</li>
56
+ <li>Fixed misc translation issues.</li>
57
+ <li>Fixed image uploads if FORCE_SSL_ADMIN is true and site is non-ssl.</li>
58
+ </ul>
59
+
60
+ <h4>1.10.1 - 4/25/2017</h4>
61
+ <p><strong>Bug Fixes</strong></p>
62
+ <ul>
63
+ <li>Fixed issue with super admins on multisite that aren't admins of a site not being able to use the full builder.</li>
64
+ </ul>
65
+
66
+ <h4>1.10 - 04/24/2017</h4>
67
+ <p><strong>General Enhancements</strong></p>
68
+ <ul>
69
+ <li>Added User Access settings to the Page Builder admin settings for choosing which user roles can access certain features.</li>
70
+ <li>Saved rows and modules can now be created via the Builder admin menu (formerly Templates admin menu).</li>
71
+ <li>Templates, saved rows and saved modules now have their on individual pages in the admin.</li>
72
+ <li>Added caching for registering templates to prevent issues with servers that have low memory.</li>
73
+ <li>Changed priority of UI script loading to try and prevent issues with themes that load scripts that should be loaded from WordPress core.</li>
74
+ <li>Added field connections to video module embed field.</li>
75
+ <li>Added the ability to order posts in the post modules by meta value.</li>
76
+ <li>Paged post modules are now scrolled to when clicking a link to the next page.</li>
77
+ <li>Added Enormail integration to the Subscribe Form module.</li>
78
+ <li>Multiple calls to Google Fonts from the theme and plugin are now combined into one request.</li>
79
+ <li>Added connections to Number Counter module fields.</li>
80
+ <li>Added fl_builder_loop_query filter.</li>
81
+ <li>Removed the loading graphic when saving settings. Elements are now slightly faded until they are updated.</li>
82
+ <li>Module and row duplicating is now instantaneous instead of having to wait with a loading graphic.</li>
83
+ <li>All drag and drop operations now load inline instead of taking over the page with a loader.</li>
84
+ <li>Added module name to the module settings overlay tooltip.</li>
85
+ <li>Added custom field connections to Contact Form module email field.</li>
86
+ <li>Added support for exporting a single theme layout or a group of theme layouts.</li>
87
+ <li>Added support for theme layouts to the template data exporter.</li>
88
+ </ul>
89
+ <p><strong>Post Module Enhancements</strong></p>
90
+ <ul>
91
+ <li>Added “columns” layout to the layout setting.</li>
92
+ <li>Added more layout and styling settings.</li>
93
+ <li>The “no results” message is now shown when no posts are found.</li>
94
+ <li>Added a setting to show a search form if no posts are found.</li>
95
+ <li>Added the ability to exclude posts in the content filter for the query.</li>
96
+ </ul>
97
+ <p><strong>Menu Module Enhancements</strong></p>
98
+ <ul>
99
+ <li>Added “below row" option for mobile menu position.</li>
100
+ <li>Added font family setting.</li>
101
+ <li>Misc CSS improvements.</li>
102
+ </ul>
103
+ <p><strong>Changes</strong></p>
104
+ <ul>
105
+ <li>Changed Templates to Builder in the admin menu.</li>
106
+ <li>Merged Uninstall and Cache into Tools in the Page Builder admin settings.</li>
107
+ <li>Removed Editing section in the Page Builder admin settings in favor of the new User Access settings.</li>
108
+ <li>Removed Templates Admin setting in the Page Builder admin settings in favor of the new User Access settings.</li>
109
+ <li>Removed Template Data Exporter setting in the Page Builder admin settings in favor of the new User Access settings.</li>
110
+ <li>Changed edit button text on the admin edit screen for templates to say Launch Page Builder.</li>
111
+ </ul>
112
+ <p><strong>Bug Fixes</strong></p>
113
+ <ul>
114
+ <li>Fixed the builder layout shortcode not working with Beaver Themer.</li>
115
+ <li>Fixed some photos not going full-width on mobile.</li>
116
+ <li>Fixed pre-instantiated widgets not working.</li>
117
+ <li>Fixed anchor links in the theme header causing the builder done actions to show.</li>
118
+ <li>Fixed multisite issues with render query.</li>
119
+ <li>Fixed post list spacing not working when using a custom post layout.</li>
120
+ <li>Fixed layout JS breaking when you save a JS array in the code field.</li>
121
+ <li>Fixed color picker alpha slider.</li>
122
+ <li>Fixed parallax background position being applied to child rows inserted using a shortcode.</li>
123
+ <li>Fixed unescaped attributes in the heading module causing HTML errors.</li>
124
+ <li>Fixed fatal error when inserting layouts via shortcode in certain cases.</li>
125
+ <li>Fixed PHP warning when first dropping a post module on the page.</li>
126
+ </ul>
127
+
128
  <h4>1.9.5.3 - 4/4/2017</h4>
129
  <p><strong>Bug Fixes</strong></p>
130
  <ul>
1878
 
1879
  <h4>0.8.1</h4>
1880
  <p>Initial beta release.</p>
1881
+
classes/class-fl-builder-admin-posts.php CHANGED
@@ -37,10 +37,11 @@ final class FLBuilderAdminPosts {
37
 
38
  if ( in_array( $pagenow, array( 'post.php', 'post-new.php') ) ) {
39
 
 
40
  $post_types = FLBuilderModel::get_post_types();
41
  $screen = get_current_screen();
42
 
43
- if ( in_array( $screen->post_type, $post_types ) ) {
44
  add_filter( 'admin_body_class', __CLASS__ . '::body_class', 99 );
45
  add_action( 'admin_enqueue_scripts', __CLASS__ . '::styles_scripts' );
46
  add_action( 'edit_form_after_title', __CLASS__ . '::render' );
@@ -105,7 +106,7 @@ final class FLBuilderAdminPosts {
105
  {
106
  global $post;
107
 
108
- $post_type_obj = get_post_type_object ( $post->post_type );
109
  $post_type_name = strtolower( $post_type_obj->labels->singular_name );
110
  $enabled = FLBuilderModel::is_builder_enabled();
111
 
@@ -125,10 +126,14 @@ final class FLBuilderAdminPosts {
125
 
126
  if ( 'trash' != $post->post_status && current_user_can( 'edit_post', $post->ID ) && wp_check_post_lock( $post->ID ) === false ) {
127
 
128
- $post_types = FLBuilderModel::get_post_types();
129
 
130
- if ( in_array( $post->post_type, $post_types ) ) {
131
- $actions['fl-builder'] = '<a href="' . FLBuilderModel::get_edit_url() . '">' . FLBuilderModel::get_branding() . '</a>';
 
 
 
 
132
  }
133
  }
134
 
37
 
38
  if ( in_array( $pagenow, array( 'post.php', 'post-new.php') ) ) {
39
 
40
+ $render_ui = apply_filters( 'fl_builder_render_admin_edit_ui', true );
41
  $post_types = FLBuilderModel::get_post_types();
42
  $screen = get_current_screen();
43
 
44
+ if ( $render_ui && in_array( $screen->post_type, $post_types ) ) {
45
  add_filter( 'admin_body_class', __CLASS__ . '::body_class', 99 );
46
  add_action( 'admin_enqueue_scripts', __CLASS__ . '::styles_scripts' );
47
  add_action( 'edit_form_after_title', __CLASS__ . '::render' );
106
  {
107
  global $post;
108
 
109
+ $post_type_obj = get_post_type_object( $post->post_type );
110
  $post_type_name = strtolower( $post_type_obj->labels->singular_name );
111
  $enabled = FLBuilderModel::is_builder_enabled();
112
 
126
 
127
  if ( 'trash' != $post->post_status && current_user_can( 'edit_post', $post->ID ) && wp_check_post_lock( $post->ID ) === false ) {
128
 
129
+ $is_post_editable = (bool) apply_filters( 'fl_builder_is_post_editable', true, $post );
130
 
131
+ $post_types = FLBuilderModel::get_post_types();
132
+
133
+ if ( in_array( $post->post_type, $post_types ) && $is_post_editable ) {
134
+ $enabled = get_post_meta( $post->ID, '_fl_builder_enabled', true );
135
+ $dot = ' <span style="color:' . ( $enabled ? '#6bc373' : '#d9d9d9' ) . '; font-size:18px;">&bull;</span>';
136
+ $actions['fl-builder'] = '<a href="' . FLBuilderModel::get_edit_url() . '">' . FLBuilderModel::get_branding() . $dot . '</a>';
137
  }
138
  }
139
 
classes/class-fl-builder-admin-settings.php CHANGED
@@ -58,9 +58,14 @@ final class FLBuilderAdminSettings {
58
  {
59
  // Styles
60
  wp_enqueue_style( 'fl-builder-admin-settings', FL_BUILDER_URL . 'css/fl-builder-admin-settings.css', array(), FL_BUILDER_VERSION );
 
 
61
 
62
  // Scripts
63
  wp_enqueue_script( 'fl-builder-admin-settings', FL_BUILDER_URL . 'js/fl-builder-admin-settings.js', array(), FL_BUILDER_VERSION );
 
 
 
64
 
65
  // Media Uploader
66
  wp_enqueue_media();
@@ -183,26 +188,21 @@ final class FLBuilderAdminSettings {
183
  'show' => true,
184
  'priority' => 400
185
  ),
 
 
 
 
 
186
  'icons' => array(
187
  'title' => __( 'Icons', 'fl-builder' ),
188
  'show' => FL_BUILDER_LITE !== true,
189
- 'priority' => 500
190
- ),
191
- 'editing' => array(
192
- 'title' => __( 'Editing', 'fl-builder' ),
193
- 'show' => true,
194
  'priority' => 600
195
  ),
196
- 'cache' => array(
197
- 'title' => __( 'Cache', 'fl-builder' ),
198
  'show' => true,
199
  'priority' => 700
200
  ),
201
- 'uninstall' => array(
202
- 'title' => __( 'Uninstall', 'fl-builder' ),
203
- 'show' => is_network_admin() || ! self::multisite_support(),
204
- 'priority' => 800
205
- ),
206
  ) );
207
 
208
  $sorted_data = array();
@@ -253,14 +253,11 @@ final class FLBuilderAdminSettings {
253
  // Icons
254
  self::render_form( 'icons' );
255
 
256
- // Editing
257
- self::render_form( 'editing' );
258
-
259
- // Cache
260
- self::render_form( 'cache' );
261
 
262
- // Uninstall
263
- self::render_form( 'uninstall' );
264
 
265
  // Let extensions hook into form rendering.
266
  do_action( 'fl_builder_admin_settings_render_forms' );
@@ -365,7 +362,7 @@ final class FLBuilderAdminSettings {
365
  self::save_enabled_modules();
366
  self::save_enabled_post_types();
367
  self::save_enabled_icons();
368
- self::save_editing_capability();
369
  self::clear_cache();
370
  self::uninstall();
371
 
@@ -541,19 +538,16 @@ final class FLBuilderAdminSettings {
541
  }
542
 
543
  /**
544
- * Saves the editing capability.
545
  *
546
- * @since 1.0
547
  * @access private
548
  * @return void
549
  */
550
- static private function save_editing_capability()
551
  {
552
- if ( isset( $_POST['fl-editing-nonce'] ) && wp_verify_nonce( $_POST['fl-editing-nonce'], 'editing' ) ) {
553
-
554
- $capability = sanitize_text_field( $_POST['fl-editing-capability'] );
555
-
556
- FLBuilderModel::update_admin_settings_option( '_fl_builder_editing_capability', $capability, true );
557
  }
558
  }
559
 
58
  {
59
  // Styles
60
  wp_enqueue_style( 'fl-builder-admin-settings', FL_BUILDER_URL . 'css/fl-builder-admin-settings.css', array(), FL_BUILDER_VERSION );
61
+ wp_enqueue_style( 'jquery-multiselect', FL_BUILDER_URL . 'css/jquery.multiselect.css', array(), FL_BUILDER_VERSION );
62
+ wp_enqueue_style( 'jquery-tiptip', FL_BUILDER_URL . 'css/jquery.tiptip.css', array(), FL_BUILDER_VERSION );
63
 
64
  // Scripts
65
  wp_enqueue_script( 'fl-builder-admin-settings', FL_BUILDER_URL . 'js/fl-builder-admin-settings.js', array(), FL_BUILDER_VERSION );
66
+ wp_enqueue_script( 'jquery-actual', FL_BUILDER_URL . 'js/jquery.actual.min.js', array( 'jquery' ), FL_BUILDER_VERSION );
67
+ wp_enqueue_script( 'jquery-multiselect', FL_BUILDER_URL . 'js/jquery.multiselect.js', array( 'jquery' ), FL_BUILDER_VERSION );
68
+ wp_enqueue_script( 'jquery-tiptip', FL_BUILDER_URL . 'js/jquery.tiptip.min.js', array( 'jquery' ), FL_BUILDER_VERSION, true );
69
 
70
  // Media Uploader
71
  wp_enqueue_media();
188
  'show' => true,
189
  'priority' => 400
190
  ),
191
+ 'user-access' => array(
192
+ 'title' => __( 'User Access', 'fl-builder' ),
193
+ 'show' => true,
194
+ 'priority' => 500
195
+ ),
196
  'icons' => array(
197
  'title' => __( 'Icons', 'fl-builder' ),
198
  'show' => FL_BUILDER_LITE !== true,
 
 
 
 
 
199
  'priority' => 600
200
  ),
201
+ 'tools' => array(
202
+ 'title' => __( 'Tools', 'fl-builder' ),
203
  'show' => true,
204
  'priority' => 700
205
  ),
 
 
 
 
 
206
  ) );
207
 
208
  $sorted_data = array();
253
  // Icons
254
  self::render_form( 'icons' );
255
 
256
+ // User Access
257
+ self::render_form( 'user-access' );
 
 
 
258
 
259
+ // Tools
260
+ self::render_form( 'tools' );
261
 
262
  // Let extensions hook into form rendering.
263
  do_action( 'fl_builder_admin_settings_render_forms' );
362
  self::save_enabled_modules();
363
  self::save_enabled_post_types();
364
  self::save_enabled_icons();
365
+ self::save_user_access();
366
  self::clear_cache();
367
  self::uninstall();
368
 
538
  }
539
 
540
  /**
541
+ * Saves the user access settings
542
  *
543
+ * @since 1.10
544
  * @access private
545
  * @return void
546
  */
547
+ static private function save_user_access()
548
  {
549
+ if ( isset( $_POST['fl-user-access-nonce'] ) && wp_verify_nonce( $_POST['fl-user-access-nonce'], 'user-access' ) ) {
550
+ FLBuilderUserAccess::save_settings( isset( $_POST['fl_user_access'] ) ? $_POST['fl_user_access'] : array() );
 
 
 
551
  }
552
  }
553
 
classes/class-fl-builder-admin.php CHANGED
@@ -61,7 +61,10 @@ final class FLBuilderAdmin {
61
 
62
  // Trigger the activation notice.
63
  self::trigger_activate_notice();
64
-
 
 
 
65
  // Flush the rewrite rules.
66
  flush_rewrite_rules();
67
  }
61
 
62
  // Trigger the activation notice.
63
  self::trigger_activate_notice();
64
+
65
+ // Allow add-ons to hook into activation.
66
+ do_action( 'fl_builder_activated' );
67
+
68
  // Flush the rewrite rules.
69
  flush_rewrite_rules();
70
  }
classes/class-fl-builder-ajax-layout.php CHANGED
@@ -26,14 +26,13 @@ final class FLBuilderAJAXLayout {
26
  */
27
  static public function render( $node_id = null, $old_node_id = null )
28
  {
 
 
29
  // Update the node ID in the post data?
30
  if ( $node_id ) {
31
  FLBuilderModel::update_post_data( 'node_id', $node_id );
32
  }
33
 
34
- // Render the draft layout CSS that will be passed back.
35
- FLBuilder::render_assets();
36
-
37
  // Register scripts needed for shortcodes and widgets.
38
  self::register_scripts();
39
 
@@ -51,6 +50,8 @@ final class FLBuilderAJAXLayout {
51
 
52
  // Render the assets.
53
  $assets = self::render_assets();
 
 
54
 
55
  // Return the response.
56
  return array(
@@ -97,11 +98,15 @@ final class FLBuilderAJAXLayout {
97
  // Add the row.
98
  $row = FLBuilderModel::add_row( $cols, $position );
99
 
 
 
100
  // Render the row.
101
  ob_start();
102
  FLBuilder::render_row( $row );
103
  $html = ob_get_clean();
104
 
 
 
105
  // Return the response.
106
  return array(
107
  'partial' => true,
@@ -140,10 +145,14 @@ final class FLBuilderAJAXLayout {
140
  // Add the group.
141
  $group = FLBuilderModel::add_col_group( $node_id, $cols, $position );
142
 
 
 
143
  // Render the group.
144
  ob_start();
145
  FLBuilder::render_column_group( $group );
146
  $html = ob_get_clean();
 
 
147
 
148
  // Return the response.
149
  return array(
@@ -180,11 +189,12 @@ final class FLBuilderAJAXLayout {
180
  * @param string $parent_id A column node ID.
181
  * @param int $position The new module position.
182
  * @param string $type The type of module.
 
183
  * @param string $template_id The ID of a module template to render.
184
  * @param string $template_type The type of template. Either "user" or "core".
185
  * @return array
186
  */
187
- static public function render_new_module( $parent_id, $position = false, $type = null, $template_id = null, $template_type = 'user' )
188
  {
189
  // Add a module template?
190
  if ( null !== $template_id ) {
@@ -199,7 +209,8 @@ final class FLBuilderAJAXLayout {
199
  }
200
  // Add a standard module.
201
  else {
202
- $module = FLBuilderModel::add_default_module( $parent_id, $type, $position );
 
203
  }
204
 
205
  // Render the new module's settings.
@@ -374,6 +385,8 @@ final class FLBuilderAJAXLayout {
374
  */
375
  static private function render_html()
376
  {
 
 
377
  // Get the partial refresh data.
378
  $partial_refresh_data = self::get_partial_refresh_data();
379
 
@@ -418,6 +431,8 @@ final class FLBuilderAJAXLayout {
418
  $html = ob_get_clean();
419
  }
420
 
 
 
421
  // Return the rendered HTML.
422
  return $html;
423
  }
@@ -436,6 +451,9 @@ final class FLBuilderAJAXLayout {
436
  $asset_ver = FLBuilderModel::get_asset_version();
437
  $assets = array( 'js' => '', 'css' => '' );
438
 
 
 
 
439
  // Render the JS.
440
  if ( $partial_refresh_data['is_partial_refresh'] ) {
441
 
@@ -470,10 +488,12 @@ final class FLBuilderAJAXLayout {
470
  }
471
  }
472
  else {
 
473
  $assets['js'] = $asset_info['js_url'] . '?ver=' . $asset_ver;
474
  }
475
 
476
  // Render the CSS.
 
477
  $assets['css'] = $asset_info['css_url'] . '?ver=' . $asset_ver;
478
 
479
  // Return the assets.
@@ -535,8 +555,7 @@ final class FLBuilderAJAXLayout {
535
  global $wp_scripts;
536
  global $wp_styles;
537
 
538
- $partial_refresh_data = self::get_partial_refresh_data();
539
- $scripts_styles = '';
540
 
541
  // Start the output buffer.
542
  ob_start();
26
  */
27
  static public function render( $node_id = null, $old_node_id = null )
28
  {
29
+ do_action( 'fl_builder_before_render_ajax_layout' );
30
+
31
  // Update the node ID in the post data?
32
  if ( $node_id ) {
33
  FLBuilderModel::update_post_data( 'node_id', $node_id );
34
  }
35
 
 
 
 
36
  // Register scripts needed for shortcodes and widgets.
37
  self::register_scripts();
38
 
50
 
51
  // Render the assets.
52
  $assets = self::render_assets();
53
+
54
+ do_action( 'fl_builder_after_render_ajax_layout' );
55
 
56
  // Return the response.
57
  return array(
98
  // Add the row.
99
  $row = FLBuilderModel::add_row( $cols, $position );
100
 
101
+ do_action( 'fl_builder_before_render_ajax_layout_html' );
102
+
103
  // Render the row.
104
  ob_start();
105
  FLBuilder::render_row( $row );
106
  $html = ob_get_clean();
107
 
108
+ do_action( 'fl_builder_after_render_ajax_layout_html' );
109
+
110
  // Return the response.
111
  return array(
112
  'partial' => true,
145
  // Add the group.
146
  $group = FLBuilderModel::add_col_group( $node_id, $cols, $position );
147
 
148
+ do_action( 'fl_builder_before_render_ajax_layout_html' );
149
+
150
  // Render the group.
151
  ob_start();
152
  FLBuilder::render_column_group( $group );
153
  $html = ob_get_clean();
154
+
155
+ do_action( 'fl_builder_after_render_ajax_layout_html' );
156
 
157
  // Return the response.
158
  return array(
189
  * @param string $parent_id A column node ID.
190
  * @param int $position The new module position.
191
  * @param string $type The type of module.
192
+ * @param string $alias Module alias slug if this module is an alias.
193
  * @param string $template_id The ID of a module template to render.
194
  * @param string $template_type The type of template. Either "user" or "core".
195
  * @return array
196
  */
197
+ static public function render_new_module( $parent_id, $position = false, $type = null, $alias = null, $template_id = null, $template_type = 'user' )
198
  {
199
  // Add a module template?
200
  if ( null !== $template_id ) {
209
  }
210
  // Add a standard module.
211
  else {
212
+ $defaults = FLBuilderModel::get_module_alias_settings( $alias );
213
+ $module = FLBuilderModel::add_default_module( $parent_id, $type, $position, $defaults );
214
  }
215
 
216
  // Render the new module's settings.
385
  */
386
  static private function render_html()
387
  {
388
+ do_action( 'fl_builder_before_render_ajax_layout_html' );
389
+
390
  // Get the partial refresh data.
391
  $partial_refresh_data = self::get_partial_refresh_data();
392
 
431
  $html = ob_get_clean();
432
  }
433
 
434
+ do_action( 'fl_builder_after_render_ajax_layout_html' );
435
+
436
  // Return the rendered HTML.
437
  return $html;
438
  }
451
  $asset_ver = FLBuilderModel::get_asset_version();
452
  $assets = array( 'js' => '', 'css' => '' );
453
 
454
+ // Ensure global assets are rendered.
455
+ FLBuilder::clear_enqueued_global_assets();
456
+
457
  // Render the JS.
458
  if ( $partial_refresh_data['is_partial_refresh'] ) {
459
 
488
  }
489
  }
490
  else {
491
+ FLBuilder::render_js();
492
  $assets['js'] = $asset_info['js_url'] . '?ver=' . $asset_ver;
493
  }
494
 
495
  // Render the CSS.
496
+ FLBuilder::render_css();
497
  $assets['css'] = $asset_info['css_url'] . '?ver=' . $asset_ver;
498
 
499
  // Return the assets.
555
  global $wp_scripts;
556
  global $wp_styles;
557
 
558
+ $scripts_styles = '';
 
559
 
560
  // Start the output buffer.
561
  ob_start();
classes/class-fl-builder-ajax.php CHANGED
@@ -123,7 +123,7 @@ final class FLBuilderAJAX {
123
  self::add_action( 'copy_row', 'FLBuilderAJAXLayout::copy_row', array( 'node_id' ) );
124
  self::add_action( 'render_new_column_group', 'FLBuilderAJAXLayout::render_new_column_group', array( 'node_id', 'cols', 'position' ) );
125
  self::add_action( 'render_new_columns', 'FLBuilderAJAXLayout::render_new_columns', array( 'node_id', 'insert', 'type', 'nested' ) );
126
- self::add_action( 'render_new_module', 'FLBuilderAJAXLayout::render_new_module', array( 'parent_id', 'position', 'type', 'template_id', 'template_type' ) );
127
  self::add_action( 'copy_module', 'FLBuilderAJAXLayout::copy_module', array( 'node_id' ) );
128
 
129
  // FLBuilderServices
123
  self::add_action( 'copy_row', 'FLBuilderAJAXLayout::copy_row', array( 'node_id' ) );
124
  self::add_action( 'render_new_column_group', 'FLBuilderAJAXLayout::render_new_column_group', array( 'node_id', 'cols', 'position' ) );
125
  self::add_action( 'render_new_columns', 'FLBuilderAJAXLayout::render_new_columns', array( 'node_id', 'insert', 'type', 'nested' ) );
126
+ self::add_action( 'render_new_module', 'FLBuilderAJAXLayout::render_new_module', array( 'parent_id', 'position', 'type', 'alias', 'template_id', 'template_type' ) );
127
  self::add_action( 'copy_module', 'FLBuilderAJAXLayout::copy_module', array( 'node_id' ) );
128
 
129
  // FLBuilderServices
classes/class-fl-builder-auto-suggest.php CHANGED
@@ -107,55 +107,64 @@ final class FLBuilderAutoSuggest {
107
  *
108
  * @since 1.2.3
109
  * @return array
110
- */
111
  static public function posts()
112
  {
113
  global $wpdb;
114
-
115
- $data = array();
116
  $like = self::get_like();
117
  $type = esc_sql($_REQUEST['fl_as_action_data']);
118
-
119
- $posts = $wpdb->get_results("
120
- SELECT ID, post_title FROM {$wpdb->posts}
121
- WHERE post_title LIKE '%{$like}%'
122
- AND post_type = '{$type}'
123
  AND post_status = 'publish'
124
- ");
125
-
126
  foreach($posts as $post) {
127
  $data[] = array('name' => $post->post_title, 'value' => $post->ID);
128
  }
129
-
130
  return $data;
131
  }
132
-
133
  /**
134
  * Returns data for selected posts.
135
  *
136
  * @since 1.2.3
137
  * @param string $ids The selected post ids.
138
  * @return array An array of post data.
139
- */
140
  static public function posts_value($ids)
141
  {
142
  global $wpdb;
143
-
144
  $data = array();
145
-
146
- if(!empty($ids)) {
147
-
148
- $ids = implode(",", array_filter(explode(",", $ids), 'intval'));
149
- $posts = $wpdb->get_results("SELECT ID, post_title FROM {$wpdb->posts} WHERE ID IN ({$ids}) ORDER BY FIELD(ID, {$ids})");
150
-
 
 
 
 
 
 
 
 
 
151
  foreach($posts as $post) {
152
  $data[] = array('name' => $post->post_title, 'value' => $post->ID);
153
  }
154
  }
155
-
156
  return $data;
157
  }
158
-
159
  /**
160
  * Returns data for term auto suggest queries.
161
  *
@@ -210,47 +219,55 @@ final class FLBuilderAutoSuggest {
210
  *
211
  * @since 1.2.3
212
  * @return array
213
- */
214
  static public function users()
215
  {
216
  global $wpdb;
217
-
218
  $data = array();
219
  $like = self::get_like();
220
- $users = $wpdb->get_results("SELECT * FROM {$wpdb->users} WHERE user_login LIKE '%{$like}%'");
221
-
222
  foreach($users as $user) {
223
  $data[] = array('name' => $user->user_login, 'value' => $user->ID);
224
  }
225
-
226
  return $data;
227
  }
228
-
229
  /**
230
  * Returns data for selected users.
231
  *
232
  * @since 1.2.3
233
  * @param string $ids The selected user ids.
234
  * @return array An array of user data.
235
- */
236
  static public function users_value($ids)
237
  {
238
  global $wpdb;
239
-
240
  $data = array();
241
-
242
  if(!empty($ids)) {
243
-
244
- $users = $wpdb->get_results("SELECT * FROM {$wpdb->users} WHERE ID IN ({$ids})");
245
-
 
 
 
 
 
 
 
 
 
246
  foreach($users as $user) {
247
  $data[] = array('name' => $user->user_login, 'value' => $user->ID);
248
  }
249
  }
250
-
251
  return $data;
252
  }
253
-
254
  /**
255
  * Returns data for link auto suggest queries.
256
  *
@@ -269,18 +286,23 @@ final class FLBuilderAutoSuggest {
269
  foreach($types as $slug => $type) {
270
  $slugs[] = esc_sql($slug);
271
  }
272
-
273
- $posts = $wpdb->get_results("
274
- SELECT ID, post_title FROM {$wpdb->posts}
275
- WHERE post_title LIKE '%{$like}%'
276
- AND post_type IN ('" . implode("','", $slugs) . "')
277
- AND post_status = 'publish'
278
- ");
279
-
 
 
 
 
 
280
  foreach($posts as $post) {
281
  $data[] = array('name' => $post->post_title, 'value' => get_permalink($post->ID));
282
  }
283
-
284
  return $data;
285
  }
286
- }
107
  *
108
  * @since 1.2.3
109
  * @return array
110
+ */
111
  static public function posts()
112
  {
113
  global $wpdb;
114
+
115
+ $data = array();
116
  $like = self::get_like();
117
  $type = esc_sql($_REQUEST['fl_as_action_data']);
118
+
119
+ $posts = $wpdb->get_results( $wpdb->prepare( "
120
+ SELECT ID, post_title FROM {$wpdb->posts}
121
+ WHERE post_title LIKE %s
122
+ AND post_type = %s
123
  AND post_status = 'publish'
124
+ ", '%' . $like . '%', $type ) );
125
+
126
  foreach($posts as $post) {
127
  $data[] = array('name' => $post->post_title, 'value' => $post->ID);
128
  }
129
+
130
  return $data;
131
  }
132
+
133
  /**
134
  * Returns data for selected posts.
135
  *
136
  * @since 1.2.3
137
  * @param string $ids The selected post ids.
138
  * @return array An array of post data.
139
+ */
140
  static public function posts_value($ids)
141
  {
142
  global $wpdb;
143
+
144
  $data = array();
145
+
146
+ if( ! empty( $ids ) ) {
147
+
148
+ $order = implode(",", array_filter(explode(",", $ids), 'intval'));
149
+ $list = explode( ',', $ids );
150
+ $how_many = count($list);
151
+ $placeholders = array_fill(0, $how_many, '%d');
152
+ $format = implode(', ', $placeholders);
153
+
154
+ $query = "SELECT ID, post_title FROM {$wpdb->posts} WHERE ID IN ($format) ORDER BY FIELD(ID, $order)";
155
+
156
+ // @codingStandardsIgnoreStart
157
+ $posts = $wpdb->get_results( $wpdb->prepare( $query, $list ) );
158
+ // @codingStandardsIgnoreEnd
159
+
160
  foreach($posts as $post) {
161
  $data[] = array('name' => $post->post_title, 'value' => $post->ID);
162
  }
163
  }
164
+
165
  return $data;
166
  }
167
+
168
  /**
169
  * Returns data for term auto suggest queries.
170
  *
219
  *
220
  * @since 1.2.3
221
  * @return array
222
+ */
223
  static public function users()
224
  {
225
  global $wpdb;
226
+
227
  $data = array();
228
  $like = self::get_like();
229
+ $users = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->users} WHERE user_login LIKE %s", '%' . $like . '%' ) );
230
+
231
  foreach($users as $user) {
232
  $data[] = array('name' => $user->user_login, 'value' => $user->ID);
233
  }
234
+
235
  return $data;
236
  }
237
+
238
  /**
239
  * Returns data for selected users.
240
  *
241
  * @since 1.2.3
242
  * @param string $ids The selected user ids.
243
  * @return array An array of user data.
244
+ */
245
  static public function users_value($ids)
246
  {
247
  global $wpdb;
248
+
249
  $data = array();
250
+
251
  if(!empty($ids)) {
252
+
253
+ $list = explode( ',', $ids );
254
+ $how_many = count($list);
255
+ $placeholders = array_fill(0, $how_many, '%d');
256
+ $format = implode(', ', $placeholders);
257
+
258
+ $query = "SELECT * FROM {$wpdb->users} WHERE ID IN ($format)";
259
+
260
+ // @codingStandardsIgnoreStart
261
+ $users = $wpdb->get_results( $wpdb->prepare( $query, $list ) );
262
+ // @codingStandardsIgnoreEnd
263
+
264
  foreach($users as $user) {
265
  $data[] = array('name' => $user->user_login, 'value' => $user->ID);
266
  }
267
  }
 
268
  return $data;
269
  }
270
+
271
  /**
272
  * Returns data for link auto suggest queries.
273
  *
286
  foreach($types as $slug => $type) {
287
  $slugs[] = esc_sql($slug);
288
  }
289
+
290
+ // we cant use an array of arrays for prepare() so use sprintf 1st.
291
+ $query = sprintf( "SELECT ID, post_title FROM {$wpdb->posts}
292
+ WHERE post_title LIKE %%s
293
+ AND post_type IN ('%s')
294
+ AND post_status = 'publish'",
295
+ implode("', '", $slugs)
296
+ );
297
+
298
+ // @codingStandardsIgnoreStart
299
+ $posts = $wpdb->get_results( $wpdb->prepare( $query, '%' . esc_sql( $like ) . '%' ) );
300
+ // @codingStandardsIgnoreEnd
301
+
302
  foreach($posts as $post) {
303
  $data[] = array('name' => $post->post_title, 'value' => get_permalink($post->ID));
304
  }
305
+
306
  return $data;
307
  }
308
+ }
classes/class-fl-builder-color.php CHANGED
@@ -36,8 +36,11 @@ final class FLBuilderColor {
36
  static public function adjust_brightness($hex, $steps, $type)
37
  {
38
  // Get rgb vars.
39
- extract(self::hex_to_rgb($hex));
40
-
 
 
 
41
  // Should we darken the color?
42
  if($type == 'reverse' && $r + $g + $b > 382){
43
  $steps = -$steps;
36
  static public function adjust_brightness($hex, $steps, $type)
37
  {
38
  // Get rgb vars.
39
+ $rgb = self::hex_to_rgb($hex);
40
+ $r = $rgb['r'];
41
+ $g = $rgb['g'];
42
+ $b = $rgb['b'];
43
+
44
  // Should we darken the color?
45
  if($type == 'reverse' && $r + $g + $b > 382){
46
  $steps = -$steps;
classes/class-fl-builder-export.php CHANGED
@@ -57,9 +57,10 @@ final class FLBuilderExport {
57
  */
58
  static public function templates_data()
59
  {
 
60
  $data = array();
61
  $query = new WP_Query( array(
62
- 'post_type' => 'fl-builder-template',
63
  'orderby' => 'title',
64
  'order' => 'ASC',
65
  'posts_per_page' => '-1'
@@ -89,7 +90,7 @@ final class FLBuilderExport {
89
  if ( ! current_user_can( 'export' ) ) {
90
  return;
91
  }
92
- if ( 'fl-builder-template' != $args['content'] ) {
93
  return;
94
  }
95
  if ( ! isset( $_REQUEST['fl-builder-template-export-select'] ) ) {
57
  */
58
  static public function templates_data()
59
  {
60
+ $type = isset( $_POST['type'] ) ? sanitize_text_field( $_POST['type'] ) : 'fl-builder-template';
61
  $data = array();
62
  $query = new WP_Query( array(
63
+ 'post_type' => $type,
64
  'orderby' => 'title',
65
  'order' => 'ASC',
66
  'posts_per_page' => '-1'
90
  if ( ! current_user_can( 'export' ) ) {
91
  return;
92
  }
93
+ if ( ! in_array( $args['content'], array( 'fl-builder-template', 'fl-theme-layout' ) ) ) {
94
  return;
95
  }
96
  if ( ! isset( $_REQUEST['fl-builder-template-export-select'] ) ) {
classes/class-fl-builder-extensions.php CHANGED
@@ -11,11 +11,13 @@ final class FLBuilderExtensions {
11
  * Initalizes any extensions found in the extensions directory.
12
  *
13
  * @since 1.8
 
14
  * @return void
15
  */
16
- static public function init()
17
  {
18
- $extensions = glob( FL_BUILDER_DIR . 'extensions/*' );
 
19
 
20
  if ( ! is_array( $extensions ) ) {
21
  return;
11
  * Initalizes any extensions found in the extensions directory.
12
  *
13
  * @since 1.8
14
+ * @param string $path Path to extensions to initalize.
15
  * @return void
16
  */
17
+ static public function init( $path = null )
18
  {
19
+ $path = $path ? trailingslashit( $path ) : FL_BUILDER_DIR . 'extensions/';
20
+ $extensions = glob( $path . '*' );
21
 
22
  if ( ! is_array( $extensions ) ) {
23
  return;
classes/class-fl-builder-fonts.php CHANGED
@@ -14,6 +14,15 @@ final class FLBuilderFonts {
14
  */
15
  static private $fonts = array();
16
 
 
 
 
 
 
 
 
 
 
17
  /**
18
  * Renders the JavasCript variable for font settings dropdowns.
19
  *
@@ -247,7 +256,7 @@ final class FLBuilderFonts {
247
  self::$fonts[ $font['family'] ][] = $font['weight'];
248
  }
249
  } else {
250
- // adds a new font and height
251
  self::$fonts[ $font['family'] ] = array( $font['weight'] );
252
 
253
  }
@@ -257,8 +266,118 @@ final class FLBuilderFonts {
257
  }
258
  }
259
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  }
261
 
 
 
262
  /**
263
  * Font info class for system and Google fonts.
264
  *
@@ -2217,8 +2336,7 @@ final class FLBuilderFontFamilies {
2217
  "Molengo" => array(
2218
  "regular",
2219
  ),
2220
- "Molle" => array(
2221
- ),
2222
  "Monda" => array(
2223
  "regular",
2224
  "700",
14
  */
15
  static private $fonts = array();
16
 
17
+ /**
18
+ * @since 1.9.5
19
+ * @return void
20
+ */
21
+ static public function init()
22
+ {
23
+ add_action('wp_enqueue_scripts', __CLASS__ . '::combine_google_fonts', 99);
24
+ }
25
+
26
  /**
27
  * Renders the JavasCript variable for font settings dropdowns.
28
  *
256
  self::$fonts[ $font['family'] ][] = $font['weight'];
257
  }
258
  } else {
259
+ // adds a new font and weight
260
  self::$fonts[ $font['family'] ] = array( $font['weight'] );
261
 
262
  }
266
  }
267
  }
268
 
269
+ /**
270
+ * Combines all enqueued google font HTTP calls into one URL.
271
+ *
272
+ * @since 1.9.5
273
+ * @return void
274
+ */
275
+ static public function combine_google_fonts(){
276
+ global $wp_styles;
277
+
278
+ // Check for any enqueued `fonts.googleapis.com` from themes or plugins
279
+ if( isset( $wp_styles->queue ) ){
280
+
281
+ $google_fonts_domain = '//fonts.googleapis.com/css';
282
+ $enqueued_google_fonts = array();
283
+ $families = array();
284
+ $subsets = array();
285
+ $font_args = array();
286
+
287
+ // Collect all enqueued google fonts
288
+ foreach( $wp_styles->queue as $key => $handle ){
289
+
290
+ if ( ! isset( $wp_styles->registered[ $handle ] ) ) {
291
+ continue;
292
+ }
293
+
294
+ $style_src = $wp_styles->registered[ $handle ]->src;
295
+
296
+ if (strpos($style_src, 'fonts.googleapis.com/css') !== false) {
297
+ $url = wp_parse_url( $style_src );
298
+
299
+ if( is_string( $url['query'] ) ) {
300
+ parse_str( $url['query'], $parsed_url );
301
+
302
+ if( isset( $parsed_url['family'] ) ){
303
+
304
+ // Collect all subsets
305
+ if( isset( $parsed_url['subset'] ) ){
306
+ $subsets[] = urlencode( trim( $parsed_url['subset'] ) );
307
+ }
308
+
309
+ $font_families = explode( '|', $parsed_url['family'] );
310
+ foreach( $font_families as $parsed_font ){
311
+
312
+ $get_font = explode( ':', $parsed_font );
313
+
314
+ // Extract the font data
315
+ if( isset( $get_font[0] ) && !empty( $get_font[0] ) ){
316
+ $family = $get_font[0];
317
+ $weights = isset( $get_font[1] ) && !empty( $get_font[1] ) ? explode( ',', $get_font[1] ) : array();
318
+
319
+ // Combine weights if family has been enqueued
320
+ if( isset( $enqueued_google_fonts[ $family ] ) && $weights != $enqueued_google_fonts[ $family ]['weights'] ){
321
+ $combined_weights = array_merge($weights, $enqueued_google_fonts[ $family ]['weights']);
322
+ $enqueued_google_fonts[ $family ]['weights'] = array_unique( $combined_weights );
323
+ }
324
+ else {
325
+ $enqueued_google_fonts[ $family ] = array(
326
+ 'handle' => $handle,
327
+ 'family' => $family,
328
+ 'weights' => $weights
329
+ );
330
+
331
+ // Remove enqueued google font style, so we would only have one HTTP request.
332
+ wp_dequeue_style( $handle );
333
+ }
334
+ }
335
+ }
336
+ }
337
+ }
338
+ }
339
+ }
340
+
341
+ // Start combining all enqueued google fonts
342
+ if( count($enqueued_google_fonts) > 0 ){
343
+
344
+ foreach( $enqueued_google_fonts as $family => $data ){
345
+ // Collect all family and weights
346
+ if( !empty( $data['weights'] ) ) {
347
+ $families[] = $family .':'. implode(',', $data['weights']);
348
+ }
349
+ else {
350
+ $families[] = $family;
351
+ }
352
+ }
353
+
354
+ if( !empty( $families ) ){
355
+ $font_args['family'] = implode('|', $families);
356
+
357
+ if( !empty( $subsets ) ){
358
+ $font_args['subset'] = implode(',', $subsets);
359
+ }
360
+
361
+ $src = add_query_arg( $font_args, $google_fonts_domain );
362
+
363
+ // Enqueue google fonts into one URL request
364
+ wp_enqueue_style(
365
+ 'fl-builder-google-fonts-'. md5( $src ),
366
+ $src,
367
+ array()
368
+ );
369
+
370
+ // Clears data
371
+ $enqueued_google_fonts = array();
372
+ }
373
+ }
374
+ }
375
+ }
376
+
377
  }
378
 
379
+ FLBuilderFonts::init();
380
+
381
  /**
382
  * Font info class for system and Google fonts.
383
  *
2336
  "Molengo" => array(
2337
  "regular",
2338
  ),
2339
+ "Molle" => array(),
 
2340
  "Monda" => array(
2341
  "regular",
2342
  "700",
classes/class-fl-builder-importer.php CHANGED
@@ -137,12 +137,20 @@ final class FLBuilderImporterDataFix {
137
  * @since 1.8
138
  * @return string
139
  */
140
- static public function run( $data )
141
  {
142
- if ( empty( $data ) || @unserialize( $data ) !== false ) {
 
143
  return $data;
144
  }
145
-
 
 
 
 
 
 
 
146
  return preg_replace_callback( '!s:(\d+):([\\\\]?"[\\\\]?"|[\\\\]?"((.*?)[^\\\\])[\\\\]?");!', 'FLBuilderImporterDataFix::regex_callback', $data );
147
  }
148
 
@@ -168,9 +176,9 @@ final class FLBuilderImporterDataFix {
168
  */
169
  static private function unescape_mysql( $value )
170
  {
171
- return str_replace( array( "\\\\", "\\0", "\\n", "\\r", "\Z", "\'", '\"' ),
172
- array( "\\", "\0", "\n", "\r", "\x1a", "'", '"' ),
173
- $value );
174
  }
175
 
176
  /**
137
  * @since 1.8
138
  * @return string
139
  */
140
+ static public function run( $data )
141
  {
142
+ // return if empty
143
+ if( empty( $data ) ) {
144
  return $data;
145
  }
146
+
147
+ $data = maybe_unserialize( $data );
148
+
149
+ // return if maybe_unserialize() returns an object or array, this is good.
150
+ if( is_object( $data ) || is_array( $data ) ) {
151
+ return $data;
152
+ }
153
+
154
  return preg_replace_callback( '!s:(\d+):([\\\\]?"[\\\\]?"|[\\\\]?"((.*?)[^\\\\])[\\\\]?");!', 'FLBuilderImporterDataFix::regex_callback', $data );
155
  }
156
 
176
  */
177
  static private function unescape_mysql( $value )
178
  {
179
+ return str_replace( array( "\\\\", "\\0", "\\n", "\\r", "\Z", "\'", '\"' ),
180
+ array( "\\", "\0", "\n", "\r", "\x1a", "'", '"' ),
181
+ $value );
182
  }
183
 
184
  /**
classes/class-fl-builder-loader.php CHANGED
@@ -1,51 +1,51 @@
1
  <?php
2
 
3
  if ( ! class_exists( 'FLBuilderLoader' ) ) {
4
-
5
  /**
6
  * Responsible for setting up builder constants, classes and includes.
7
  *
8
  * @since 1.8
9
  */
10
  final class FLBuilderLoader {
11
-
12
  /**
13
  * Load the builder if it's not already loaded, otherwise
14
  * show an admin notice.
15
  *
16
  * @since 1.8
17
  * @return void
18
- */
19
  static public function init()
20
  {
21
  if ( ! function_exists( 'is_plugin_active' ) ) {
22
  include_once ABSPATH . 'wp-admin/includes/plugin.php';
23
  }
24
-
25
  $lite_dirname = 'beaver-builder-lite-version';
26
  $lite_active = is_plugin_active( $lite_dirname . '/fl-builder.php' );
27
  $plugin_dirname = basename( dirname( dirname( __FILE__ ) ) );
28
-
29
  if ( class_exists( 'FLBuilder' ) || ( $plugin_dirname != $lite_dirname && $lite_active ) ) {
30
  add_action('admin_notices', __CLASS__ . '::double_install_admin_notice');
31
  add_action('network_admin_notices', __CLASS__ . '::double_install_admin_notice');
32
  return;
33
  }
34
-
35
  self::define_constants();
36
  self::load_files();
37
  self::check_permissions();
38
  }
39
-
40
  /**
41
  * Define builder constants.
42
  *
43
  * @since 1.8
44
  * @return void
45
- */
46
  static private function define_constants()
47
  {
48
- define('FL_BUILDER_VERSION', '1.9.5.3');
49
  define('FL_BUILDER_FILE', trailingslashit(dirname(dirname(__FILE__))) . 'fl-builder.php');
50
  define('FL_BUILDER_DIR', plugin_dir_path(FL_BUILDER_FILE));
51
  define('FL_BUILDER_URL', plugins_url('/', FL_BUILDER_FILE));
@@ -57,13 +57,13 @@ if ( ! class_exists( 'FLBuilderLoader' ) ) {
57
  define('FL_BUILDER_OLD_DEMO_URL', 'http://demos.fastlinemedia.com');
58
  define('FL_BUILDER_DEMO_CACHE_URL', 'http://demos.wpbeaverbuilder.com/wp-content/uploads/bb-plugin/cache/');
59
  }
60
-
61
  /**
62
  * Loads classes and includes.
63
  *
64
  * @since 1.8
65
  * @return void
66
- */
67
  static private function load_files()
68
  {
69
  /* Classes */
@@ -88,18 +88,19 @@ if ( ! class_exists( 'FLBuilderLoader' ) ) {
88
  require_once FL_BUILDER_DIR . 'classes/class-fl-builder-shortcodes.php';
89
  require_once FL_BUILDER_DIR . 'classes/class-fl-builder-update.php';
90
  require_once FL_BUILDER_DIR . 'classes/class-fl-builder-timezones.php';
 
91
  require_once FL_BUILDER_DIR . 'classes/class-fl-builder-utils.php';
92
 
93
  /* WP CLI Commands */
94
  if ( defined( 'WP_CLI' ) ) {
95
  require __DIR__ . '/class-fl-builder-wpcli-command.php';
96
  }
97
-
98
  /* Includes */
99
  require_once FL_BUILDER_DIR . 'includes/compatibility.php';
100
  require_once FL_BUILDER_DIR . 'includes/updater/updater.php';
101
  }
102
-
103
  /**
104
  * Checks to see if we can write to files and shows
105
  * an admin notice if we can't.
@@ -107,21 +108,21 @@ if ( ! class_exists( 'FLBuilderLoader' ) ) {
107
  * @since 1.8.2
108
  * @access private
109
  * @return void
110
- */
111
  static private function check_permissions()
112
  {
113
  if ( isset( $_REQUEST['page'] ) && in_array( $_REQUEST['page'], array( 'fl-builder-settings', 'fl-builder-multisite-settings' ) ) ) {
114
-
115
  $wp_upload_dir = wp_upload_dir();
116
  $bb_upload_dir = FLBuilderModel::get_upload_dir();
117
-
118
  if ( ! is_writable( $wp_upload_dir['basedir'] ) || ! is_writable( $bb_upload_dir['path'] ) ) {
119
  add_action('admin_notices', __CLASS__ . '::permissions_admin_notice');
120
  add_action('network_admin_notices', __CLASS__ . '::permissions_admin_notice');
121
  }
122
  }
123
  }
124
-
125
  /**
126
  * Shows an admin notice if we can't write to files.
127
  *
@@ -131,10 +132,10 @@ if ( ! class_exists( 'FLBuilderLoader' ) ) {
131
  static public function permissions_admin_notice()
132
  {
133
  $message = __( 'Beaver Builder may not be functioning correctly as it does not have permission to write files to the WordPress uploads directory on your server. Please update the WordPress uploads directory permissions before continuing or contact your host for assistance.', 'fl-builder' );
134
-
135
  self::render_admin_notice( $message, 'error' );
136
  }
137
-
138
  /**
139
  * Shows an admin notice if another version of the builder
140
  * has already been loaded before this one.
@@ -145,10 +146,10 @@ if ( ! class_exists( 'FLBuilderLoader' ) ) {
145
  static public function double_install_admin_notice()
146
  {
147
  $message = __( 'You currently have two versions of Beaver Builder active on this site. Please <a href="%s">deactivate one</a> before continuing.', 'fl-builder' );
148
-
149
  self::render_admin_notice( sprintf( $message, admin_url( 'plugins.php' ) ), 'error' );
150
  }
151
-
152
  /**
153
  * Renders an admin notice.
154
  *
@@ -157,7 +158,7 @@ if ( ! class_exists( 'FLBuilderLoader' ) ) {
157
  * @param string $message
158
  * @param string $type
159
  * @return void
160
- */
161
  static private function render_admin_notice( $message, $type = 'update' )
162
  {
163
  if ( ! is_admin() ) {
@@ -166,10 +167,10 @@ if ( ! class_exists( 'FLBuilderLoader' ) ) {
166
  else if ( ! is_user_logged_in() ) {
167
  return;
168
  }
169
- else if ( ! current_user_can( 'update_core' ) ) {
170
  return;
171
  }
172
-
173
  echo '<div class="' . $type . '">';
174
  echo '<p>' . $message . '</p>';
175
  echo '</div>';
1
  <?php
2
 
3
  if ( ! class_exists( 'FLBuilderLoader' ) ) {
4
+
5
  /**
6
  * Responsible for setting up builder constants, classes and includes.
7
  *
8
  * @since 1.8
9
  */
10
  final class FLBuilderLoader {
11
+
12
  /**
13
  * Load the builder if it's not already loaded, otherwise
14
  * show an admin notice.
15
  *
16
  * @since 1.8
17
  * @return void
18
+ */
19
  static public function init()
20
  {
21
  if ( ! function_exists( 'is_plugin_active' ) ) {
22
  include_once ABSPATH . 'wp-admin/includes/plugin.php';
23
  }
24
+
25
  $lite_dirname = 'beaver-builder-lite-version';
26
  $lite_active = is_plugin_active( $lite_dirname . '/fl-builder.php' );
27
  $plugin_dirname = basename( dirname( dirname( __FILE__ ) ) );
28
+
29
  if ( class_exists( 'FLBuilder' ) || ( $plugin_dirname != $lite_dirname && $lite_active ) ) {
30
  add_action('admin_notices', __CLASS__ . '::double_install_admin_notice');
31
  add_action('network_admin_notices', __CLASS__ . '::double_install_admin_notice');
32
  return;
33
  }
34
+
35
  self::define_constants();
36
  self::load_files();
37
  self::check_permissions();
38
  }
39
+
40
  /**
41
  * Define builder constants.
42
  *
43
  * @since 1.8
44
  * @return void
45
+ */
46
  static private function define_constants()
47
  {
48
+ define('FL_BUILDER_VERSION', '1.10.4');
49
  define('FL_BUILDER_FILE', trailingslashit(dirname(dirname(__FILE__))) . 'fl-builder.php');
50
  define('FL_BUILDER_DIR', plugin_dir_path(FL_BUILDER_FILE));
51
  define('FL_BUILDER_URL', plugins_url('/', FL_BUILDER_FILE));
57
  define('FL_BUILDER_OLD_DEMO_URL', 'http://demos.fastlinemedia.com');
58
  define('FL_BUILDER_DEMO_CACHE_URL', 'http://demos.wpbeaverbuilder.com/wp-content/uploads/bb-plugin/cache/');
59
  }
60
+
61
  /**
62
  * Loads classes and includes.
63
  *
64
  * @since 1.8
65
  * @return void
66
+ */
67
  static private function load_files()
68
  {
69
  /* Classes */
88
  require_once FL_BUILDER_DIR . 'classes/class-fl-builder-shortcodes.php';
89
  require_once FL_BUILDER_DIR . 'classes/class-fl-builder-update.php';
90
  require_once FL_BUILDER_DIR . 'classes/class-fl-builder-timezones.php';
91
+ require_once FL_BUILDER_DIR . 'classes/class-fl-builder-user-access.php';
92
  require_once FL_BUILDER_DIR . 'classes/class-fl-builder-utils.php';
93
 
94
  /* WP CLI Commands */
95
  if ( defined( 'WP_CLI' ) ) {
96
  require __DIR__ . '/class-fl-builder-wpcli-command.php';
97
  }
98
+
99
  /* Includes */
100
  require_once FL_BUILDER_DIR . 'includes/compatibility.php';
101
  require_once FL_BUILDER_DIR . 'includes/updater/updater.php';
102
  }
103
+
104
  /**
105
  * Checks to see if we can write to files and shows
106
  * an admin notice if we can't.
108
  * @since 1.8.2
109
  * @access private
110
  * @return void
111
+ */
112
  static private function check_permissions()
113
  {
114
  if ( isset( $_REQUEST['page'] ) && in_array( $_REQUEST['page'], array( 'fl-builder-settings', 'fl-builder-multisite-settings' ) ) ) {
115
+
116
  $wp_upload_dir = wp_upload_dir();
117
  $bb_upload_dir = FLBuilderModel::get_upload_dir();
118
+
119
  if ( ! is_writable( $wp_upload_dir['basedir'] ) || ! is_writable( $bb_upload_dir['path'] ) ) {
120
  add_action('admin_notices', __CLASS__ . '::permissions_admin_notice');
121
  add_action('network_admin_notices', __CLASS__ . '::permissions_admin_notice');
122
  }
123
  }
124
  }
125
+
126
  /**
127
  * Shows an admin notice if we can't write to files.
128
  *
132
  static public function permissions_admin_notice()
133
  {
134
  $message = __( 'Beaver Builder may not be functioning correctly as it does not have permission to write files to the WordPress uploads directory on your server. Please update the WordPress uploads directory permissions before continuing or contact your host for assistance.', 'fl-builder' );
135
+
136
  self::render_admin_notice( $message, 'error' );
137
  }
138
+
139
  /**
140
  * Shows an admin notice if another version of the builder
141
  * has already been loaded before this one.
146
  static public function double_install_admin_notice()
147
  {
148
  $message = __( 'You currently have two versions of Beaver Builder active on this site. Please <a href="%s">deactivate one</a> before continuing.', 'fl-builder' );
149
+
150
  self::render_admin_notice( sprintf( $message, admin_url( 'plugins.php' ) ), 'error' );
151
  }
152
+
153
  /**
154
  * Renders an admin notice.
155
  *
158
  * @param string $message
159
  * @param string $type
160
  * @return void
161
+ */
162
  static private function render_admin_notice( $message, $type = 'update' )
163
  {
164
  if ( ! is_admin() ) {
167
  else if ( ! is_user_logged_in() ) {
168
  return;
169
  }
170
+ else if ( ! current_user_can( 'update_plugins' ) ) {
171
  return;
172
  }
173
+
174
  echo '<div class="' . $type . '">';
175
  echo '<p>' . $message . '</p>';
176
  echo '</div>';
classes/class-fl-builder-loop.php CHANGED
@@ -23,20 +23,65 @@ final class FLBuilderLoop {
23
  */
24
  static public function init()
25
  {
26
- add_filter( 'found_posts', __CLASS__ . '::found_posts', 1, 2 );
27
- add_action( 'init', __CLASS__ . '::init_rewrite_rules' );
28
- add_filter( 'redirect_canonical', __CLASS__ . '::override_canonical', 1, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  }
30
 
31
  /**
32
  * Returns a new instance of WP_Query based on
33
  * the provided module settings.
34
  *
35
- * @since 1.2.3
36
  * @param object $settings Module settings to use for the query.
37
  * @return object A WP_Query instance.
38
  */
39
- static public function query($settings)
40
  {
41
  $posts_per_page = empty($settings->posts_per_page) ? 10 : $settings->posts_per_page;
42
  $post_type = empty($settings->post_type) ? 'post' : $settings->post_type;
@@ -72,7 +117,6 @@ final class FLBuilderLoop {
72
  'post_type' => $post_type,
73
  'orderby' => $order_by,
74
  'order' => $order,
75
- 'author' => $users,
76
  'tax_query' => array('relation' => 'AND'),
77
  'ignore_sticky_posts' => true,
78
  'offset' => $paged_offset,
@@ -81,12 +125,38 @@ final class FLBuilderLoop {
81
  'fields' => $fields
82
  ) );
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  // Build the taxonomy query.
85
  $taxonomies = self::taxonomies($post_type);
86
 
87
  foreach($taxonomies as $tax_slug => $tax) {
88
 
89
  $tax_value = '';
 
 
 
 
 
 
 
 
90
 
91
  // New settings slug.
92
  if(isset($settings->{'tax_' . $post_type . '_' . $tax_slug})) {
@@ -102,18 +172,28 @@ final class FLBuilderLoop {
102
  $args['tax_query'][] = array(
103
  'taxonomy' => $tax_slug,
104
  'field' => 'id',
105
- 'terms' => explode(',', $tax_value)
 
106
  );
107
  }
108
  }
109
 
110
- // Post in query.
111
  if(isset($settings->{'posts_' . $post_type})) {
112
 
113
  $ids = $settings->{'posts_' . $post_type};
 
114
 
 
 
 
 
 
 
 
 
115
  if(!empty($ids)) {
116
- $args['post__in'] = explode(',', $settings->{'posts_' . $post_type});
117
  }
118
  }
119
 
@@ -211,22 +291,27 @@ final class FLBuilderLoop {
211
  $page_prefix = empty($permalink_structure) ? 'paged' : 'page';
212
  }
213
 
214
- if(empty($permalink_structure)) {
215
  $format = '&'. $page_prefix .'=%#%';
216
  }
217
-
218
  else if ("/" == substr($base, -1)) {
219
  $format = $page_prefix . '/%#%/';
220
  }
221
  else {
222
  $format = '/'. $page_prefix .'/%#%';
223
  }
224
-
 
 
 
 
 
 
225
  $pos = strrpos($base, "paged-");
226
  if ( $pos ) {
227
- $base = substr_replace( $base, '', $pos, strlen( $base ) );
228
  }
229
-
230
  echo paginate_links(array(
231
  'base' => $base . '%_%',
232
  'format' => $format,
@@ -296,6 +381,7 @@ final class FLBuilderLoop {
296
 
297
  unset($post_types['attachment']);
298
  unset($post_types['fl-builder-template']);
 
299
 
300
  return $post_types;
301
  }
@@ -339,6 +425,30 @@ final class FLBuilderLoop {
339
 
340
  the_time( $format );
341
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  }
343
 
344
  FLBuilderLoop::init();
23
  */
24
  static public function init()
25
  {
26
+ // Actions
27
+ add_action( 'fl_builder_before_control_suggest', __CLASS__ . '::render_match_select', 10, 4 );
28
+ add_action( 'init', __CLASS__ . '::init_rewrite_rules' );
29
+
30
+ // Filters
31
+ add_filter( 'found_posts', __CLASS__ . '::found_posts', 1, 2 );
32
+ add_filter( 'redirect_canonical', __CLASS__ . '::override_canonical', 1, 2 );
33
+ }
34
+
35
+ /**
36
+ * Returns either a clone of the main query or a new instance of
37
+ * WP_Query based on the provided module settings.
38
+ *
39
+ * @since 1.2.3
40
+ * @param object $settings Module settings to use for the query.
41
+ * @return object A WP_Query instance.
42
+ */
43
+ static public function query( $settings )
44
+ {
45
+ do_action( 'fl_builder_loop_before_query', $settings );
46
+
47
+ if ( isset( $settings->data_source ) && 'main_query' == $settings->data_source ) {
48
+ $query = self::main_query();
49
+ }
50
+ else {
51
+ $query = self::custom_query( $settings );
52
+ }
53
+
54
+ do_action( 'fl_builder_loop_after_query', $settings );
55
+
56
+ return apply_filters( 'fl_builder_loop_query', $query, $settings );
57
+ }
58
+
59
+ /**
60
+ * Returns a clone of the main query with the post data reset.
61
+ *
62
+ * @since 1.10
63
+ * @return object A WP_Query instance.
64
+ */
65
+ static public function main_query()
66
+ {
67
+ global $wp_query;
68
+
69
+ $query = clone $wp_query;
70
+ $query->rewind_posts();
71
+ $query->reset_postdata();
72
+
73
+ return $query;
74
  }
75
 
76
  /**
77
  * Returns a new instance of WP_Query based on
78
  * the provided module settings.
79
  *
80
+ * @since 1.10
81
  * @param object $settings Module settings to use for the query.
82
  * @return object A WP_Query instance.
83
  */
84
+ static public function custom_query($settings)
85
  {
86
  $posts_per_page = empty($settings->posts_per_page) ? 10 : $settings->posts_per_page;
87
  $post_type = empty($settings->post_type) ? 'post' : $settings->post_type;
117
  'post_type' => $post_type,
118
  'orderby' => $order_by,
119
  'order' => $order,
 
120
  'tax_query' => array('relation' => 'AND'),
121
  'ignore_sticky_posts' => true,
122
  'offset' => $paged_offset,
125
  'fields' => $fields
126
  ) );
127
 
128
+ // Order by meta value arg.
129
+ if ( strstr( $order_by, 'meta_value' ) ) {
130
+ $args['meta_key'] = $settings->order_by_meta_key;
131
+ }
132
+
133
+ // Build the author query.
134
+ if ( ! empty( $users ) ) {
135
+
136
+ $arg = 'author__in';
137
+
138
+ // Set to NOT IN if matching is present and set to 0.
139
+ if(isset($settings->users_matching) && !$settings->users_matching) {
140
+ $arg = 'author__not_in';
141
+ }
142
+
143
+ $args[ $arg ] = $users;
144
+ }
145
+
146
  // Build the taxonomy query.
147
  $taxonomies = self::taxonomies($post_type);
148
 
149
  foreach($taxonomies as $tax_slug => $tax) {
150
 
151
  $tax_value = '';
152
+ $operator = 'IN';
153
+
154
+ // Set to NOT IN if matching is present and set to 0.
155
+ if(isset($settings->{'tax_' . $post_type . '_' . $tax_slug . '_matching'})) {
156
+ if (!$settings->{'tax_' . $post_type . '_' . $tax_slug . '_matching'}) {
157
+ $operator = 'NOT IN';
158
+ }
159
+ }
160
 
161
  // New settings slug.
162
  if(isset($settings->{'tax_' . $post_type . '_' . $tax_slug})) {
172
  $args['tax_query'][] = array(
173
  'taxonomy' => $tax_slug,
174
  'field' => 'id',
175
+ 'terms' => explode(',', $tax_value),
176
+ 'operator' => $operator
177
  );
178
  }
179
  }
180
 
181
+ // Post in/not in query.
182
  if(isset($settings->{'posts_' . $post_type})) {
183
 
184
  $ids = $settings->{'posts_' . $post_type};
185
+ $arg = 'post__in';
186
 
187
+ // Set to NOT IN if matching is present and set to 0.
188
+ if(isset($settings->{'posts_' . $post_type . '_matching'})) {
189
+ if (!$settings->{'posts_' . $post_type . '_matching'}) {
190
+ $arg = 'post__not_in';
191
+ }
192
+ }
193
+
194
+ // Add the args if we have IDs.
195
  if(!empty($ids)) {
196
+ $args[ $arg ] = explode(',', $settings->{'posts_' . $post_type});
197
  }
198
  }
199
 
291
  $page_prefix = empty($permalink_structure) ? 'paged' : 'page';
292
  }
293
 
294
+ if(empty($permalink_structure) || is_search()) {
295
  $format = '&'. $page_prefix .'=%#%';
296
  }
 
297
  else if ("/" == substr($base, -1)) {
298
  $format = $page_prefix . '/%#%/';
299
  }
300
  else {
301
  $format = '/'. $page_prefix .'/%#%';
302
  }
303
+
304
+ // Fix for wpml pagination
305
+ // @since 1.10.2
306
+ if( ! empty( $permalink_structure ) && isset( $_GET['lang'] ) ) {
307
+ $base = untrailingslashit( add_query_arg( array( 'lang' => false ), $base ) );
308
+ }
309
+
310
  $pos = strrpos($base, "paged-");
311
  if ( $pos ) {
312
+ $base = substr_replace( $base, '', $pos, strlen( $base ) );
313
  }
314
+
315
  echo paginate_links(array(
316
  'base' => $base . '%_%',
317
  'format' => $format,
381
 
382
  unset($post_types['attachment']);
383
  unset($post_types['fl-builder-template']);
384
+ unset($post_types['fl-theme-layout']);
385
 
386
  return $post_types;
387
  }
425
 
426
  the_time( $format );
427
  }
428
+
429
+ /**
430
+ * Renders the select for matching or not matching filters in
431
+ * a module's loop builder settings.
432
+ *
433
+ * @since 1.10
434
+ * @param string $name
435
+ * @param string $value
436
+ * @param array $field
437
+ * @param object $settings
438
+ * @return void
439
+ */
440
+ static public function render_match_select( $name, $value, $field, $settings )
441
+ {
442
+ if ( ! isset( $field['matching'] ) || ! $field['matching'] ) {
443
+ return;
444
+ }
445
+
446
+ if ( ! isset( $settings->{ $name . '_matching' } ) ) {
447
+ $settings->{ $name . '_matching' } = '1';
448
+ }
449
+
450
+ include FL_BUILDER_DIR . 'includes/loop-settings-matching.php';
451
+ }
452
  }
453
 
454
  FLBuilderLoop::init();
classes/class-fl-builder-model.php CHANGED
@@ -12,7 +12,7 @@ final class FLBuilderModel {
12
  * An array that contains the sizes for columns
13
  * in each row layout.
14
  *
15
- * @since 1.0
16
  * @var array $row_layouts
17
  */
18
  static public $row_layouts = array(
@@ -30,7 +30,7 @@ final class FLBuilderModel {
30
  /**
31
  * An array that contains data for each registered settings form.
32
  *
33
- * @since 1.0
34
  * @var array $settings_forms
35
  */
36
  static public $settings_forms = array();
@@ -38,7 +38,7 @@ final class FLBuilderModel {
38
  /**
39
  * An array used to cache default values for settings forms.
40
  *
41
- * @since 1.0
42
  * @var array $settings_form_defaults
43
  */
44
  static public $settings_form_defaults = array();
@@ -46,24 +46,42 @@ final class FLBuilderModel {
46
  /**
47
  * An array that instances for each registered module.
48
  *
49
- * @since 1.0
50
  * @var array $modules
51
  */
52
  static public $modules = array();
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  /**
55
  * Cached global settings.
56
  *
57
  * @access private
58
  * @var array $global_settings
59
  */
60
- private static $global_settings;
61
 
62
  /**
63
  * The last node id that was generated by the builder.
64
  * This is saved to ensure the next node id is unique.
65
  *
66
- * @since 1.0
67
  * @access private
68
  * @var string $last_generated_node_id
69
  */
@@ -73,16 +91,31 @@ final class FLBuilderModel {
73
  * Cached post data from either the $_POST array
74
  * or from the fl_builder_data post variable.
75
  *
76
- * @since 1.0
77
  * @access private
78
  * @var array $post_data
79
  */
80
  static private $post_data = null;
81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  /**
83
  * An array of cached published layout data by post_id.
84
  *
85
- * @since 1.0
86
  * @access private
87
  * @var array $published_layout_data
88
  */
@@ -91,7 +124,7 @@ final class FLBuilderModel {
91
  /**
92
  * An array of cached draft layout data by post_id.
93
  *
94
- * @since 1.0
95
  * @access private
96
  * @var array $draft_layout_data
97
  */
@@ -105,7 +138,17 @@ final class FLBuilderModel {
105
  * @var array $templates
106
  */
107
  static private $templates = array();
108
-
 
 
 
 
 
 
 
 
 
 
109
  /**
110
  * An array of cached post IDs for node templates.
111
  *
@@ -114,7 +157,7 @@ final class FLBuilderModel {
114
  * @var array $node_template_post_ids
115
  */
116
  static private $node_template_post_ids = array();
117
-
118
  /**
119
  * An array of cached types for user and node templates.
120
  *
@@ -127,7 +170,7 @@ final class FLBuilderModel {
127
  /**
128
  * Initialize hooks.
129
  *
130
- * @since 1.8
131
  * @return void
132
  */
133
  static public function init()
@@ -135,7 +178,7 @@ final class FLBuilderModel {
135
  /* Admin AJAX */
136
  add_action('wp_ajax_fl_builder_disable', __CLASS__ . '::disable');
137
  add_action('wp_ajax_fl_builder_duplicate_wpml_layout', __CLASS__ . '::duplicate_wpml_layout');
138
-
139
  /* Actions */
140
  add_action('init', __CLASS__ . '::load_settings', 1);
141
  add_action('init', __CLASS__ . '::load_modules', 2);
@@ -143,18 +186,18 @@ final class FLBuilderModel {
143
  add_action('save_post', __CLASS__ . '::save_revision');
144
  add_action('save_post', __CLASS__ . '::set_node_template_default_type', 10, 3);
145
  add_action('wp_restore_post_revision', __CLASS__ . '::restore_revision', 10, 2);
146
-
147
  /* Filters */
148
  add_filter('heartbeat_received', __CLASS__ . '::lock_post', 10, 2);
149
-
150
  /* Core Templates */
151
- self::register_templates( FL_BUILDER_DIR . 'data/templates.dat' );
152
  }
153
 
154
  /**
155
  * Returns a builder edit URL for a post.
156
  *
157
- * @since 1.0
158
  * @param int $post_id The post id to get an edit url for.
159
  * @return string
160
  */
@@ -175,7 +218,7 @@ final class FLBuilderModel {
175
  * Can be overridden by theme developers to use their affiliate
176
  * link using the fl_builder_upgrade_url filter.
177
  *
178
- * @since 1.0
179
  * @param array $params An array of key/value params to add to the query string.
180
  * @return string
181
  */
@@ -195,7 +238,7 @@ final class FLBuilderModel {
195
  static public function get_store_url( $path = '', $params = array() )
196
  {
197
  $url = trailingslashit( FL_BUILDER_STORE_URL . $path ) . '?' . http_build_query( $params, '', '&' );
198
-
199
  return apply_filters( 'fl_builder_store_url', $url, $path );
200
  }
201
 
@@ -203,7 +246,7 @@ final class FLBuilderModel {
203
  * Returns an array of post data from either $_POST['fl_builder_data']
204
  * or $_POST if that is not set.
205
  *
206
- * @since 1.0
207
  * @return array
208
  */
209
  static public function get_post_data()
@@ -213,17 +256,17 @@ final class FLBuilderModel {
213
  self::$post_data = array();
214
 
215
  if(isset($_POST['fl_builder_data'])) {
216
-
217
- // Decode settings if our ModSecurity fix is enabled.
218
  if ( isset( $_POST['fl_builder_data']['settings'] ) ) {
219
  $_POST['fl_builder_data']['settings'] = FLBuilderUtils::modsec_fix_decode( $_POST['fl_builder_data']['settings'] );
220
  }
221
  if ( isset( $_POST['fl_builder_data']['node_settings'] ) ) {
222
  $_POST['fl_builder_data']['node_settings'] = FLBuilderUtils::modsec_fix_decode( $_POST['fl_builder_data']['node_settings'] );
223
  }
224
-
225
  $data = FLBuilderUtils::json_decode_deep( wp_unslash( $_POST['fl_builder_data'] ) );
226
-
227
  foreach($data as $key => $val) {
228
  self::$post_data[$key] = $val;
229
  }
@@ -242,7 +285,7 @@ final class FLBuilderModel {
242
  /**
243
  * Update a value in the $post_data array.
244
  *
245
- * @since 1.0
246
  * @param string $key The post data key.
247
  * @param mixed $value The value to update.
248
  * @return void
@@ -256,9 +299,9 @@ final class FLBuilderModel {
256
 
257
  /**
258
  * Return an array of post types that the builder
259
- * is enabled to work with.
260
  *
261
- * @since 1.0
262
  * @return array
263
  */
264
  static public function get_post_types()
@@ -271,7 +314,7 @@ final class FLBuilderModel {
271
  else {
272
  $value[] = 'fl-builder-template';
273
  }
274
-
275
  return apply_filters( 'fl_builder_post_types', $value );
276
  }
277
 
@@ -279,7 +322,7 @@ final class FLBuilderModel {
279
  * Return an array of post ids that should have their
280
  * builder assets loaded globally.
281
  *
282
- * @since 1.0
283
  * @return array
284
  */
285
  static public function get_global_posts()
@@ -287,12 +330,39 @@ final class FLBuilderModel {
287
  return apply_filters('fl_builder_global_posts', array());
288
  }
289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  /**
291
  * Returns the post id for the current post that
292
  * is being displayed or worked on.
293
  *
294
- * @since 1.0
295
- * @since 1.5.9 Trying to use the global $wp_the_query instead of $post to get the post id.
296
  * @return int|bool The post id or false.
297
  */
298
  static public function get_post_id()
@@ -302,8 +372,12 @@ final class FLBuilderModel {
302
 
303
  $post_data = self::get_post_data();
304
 
 
 
 
 
305
  // Get a post ID sent in an AJAX request.
306
- if ( isset( $post_data['post_id'] ) ) {
307
  return $post_data['post_id'];
308
  }
309
  // Get a post ID from the main query.
@@ -324,7 +398,7 @@ final class FLBuilderModel {
324
  * Returns the post object for the current post that
325
  * is being worked on.
326
  *
327
- * @since 1.6.3
328
  * @return object
329
  */
330
  static public function get_post()
@@ -335,7 +409,7 @@ final class FLBuilderModel {
335
  /**
336
  * Checks to see if the site has SSL enabled or not.
337
  *
338
- * @since 1.0
339
  * @return bool
340
  */
341
  static public function is_ssl()
@@ -349,7 +423,7 @@ final class FLBuilderModel {
349
  else if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
350
  return true;
351
  }
352
-
353
  return false;
354
  }
355
 
@@ -357,13 +431,15 @@ final class FLBuilderModel {
357
  * Checks to see if the builder can be enabled for
358
  * the current post in the main query.
359
  *
360
- * @since 1.0
361
  * @return bool
362
  */
363
  static public function is_post_editable()
364
  {
365
  global $wp_the_query;
366
 
 
 
367
  if ( is_singular() && isset( $wp_the_query->post ) ) {
368
 
369
  $post = $wp_the_query->post;
@@ -371,18 +447,18 @@ final class FLBuilderModel {
371
  $user_can = current_user_can( 'edit_post', $post->ID );
372
 
373
  if ( in_array( $post->post_type, $post_types ) && $user_can ) {
374
- return true;
375
  }
376
  }
377
 
378
- return false;
379
  }
380
 
381
  /**
382
  * Called by the heartbeat API. Lock the current post
383
  * so only the current user can edit it.
384
  *
385
- * @since 1.0
386
  * @return void
387
  */
388
  static public function lock_post($response, $data)
@@ -399,7 +475,7 @@ final class FLBuilderModel {
399
  * Checks to see if the builder layout is enabled
400
  * for the current post.
401
  *
402
- * @since 1.0
403
  * @return bool
404
  */
405
  static public function is_builder_enabled()
@@ -427,28 +503,30 @@ final class FLBuilderModel {
427
  * Checks to see if the builder UI is active for
428
  * the current post in the main query.
429
  *
430
- * @since 1.0
431
  * @return bool
432
  */
433
  static public function is_builder_active()
434
  {
435
- if ( self::is_post_editable() && ! is_admin() && ! post_password_required() ) {
 
436
 
 
 
 
 
 
 
 
437
  $post_data = self::get_post_data();
438
-
439
- if ( isset( $_GET['fl_builder'] ) ) {
440
- return true;
441
- }
442
- else if ( isset( $post_data['fl_builder'] ) ) {
443
- return true;
444
- }
445
  }
446
 
447
- return false;
448
  }
449
 
450
  /**
451
- * Checks to see if this is the first time
452
  * a user has launched the builder.
453
  *
454
  * @since 1.4.9
@@ -457,10 +535,10 @@ final class FLBuilderModel {
457
  static public function is_new_user()
458
  {
459
  if ( self::is_builder_active() ) {
460
-
461
  $current_user = wp_get_current_user();
462
  $launched = get_user_meta( $current_user->ID, '_fl_builder_launched', true );
463
-
464
  if ( empty( $launched ) ) {
465
  update_user_meta( $current_user->ID, '_fl_builder_launched', 1 );
466
  return true;
@@ -515,7 +593,7 @@ final class FLBuilderModel {
515
  {
516
  global $wp_the_query;
517
 
518
- if ( self::is_post_editable() ) {
519
 
520
  $post = $wp_the_query->post;
521
  $published = self::get_layout_data( 'published' );
@@ -551,7 +629,7 @@ final class FLBuilderModel {
551
  }
552
 
553
  /**
554
- * Returns an array of paths for the upload directory
555
  * of the current site.
556
  *
557
  * @since 1.0
@@ -561,7 +639,7 @@ final class FLBuilderModel {
561
  {
562
  $wp_info = wp_upload_dir();
563
  $dir_name = basename( FL_BUILDER_DIR );
564
-
565
  // We use bb-plugin for the lite version as well.
566
  if ( $dir_name == 'beaver-builder-lite-version' ) {
567
  $dir_name = 'bb-plugin';
@@ -580,10 +658,10 @@ final class FLBuilderModel {
580
 
581
  // Create the upload dir if it doesn't exist.
582
  if ( ! file_exists( $dir_info['path'] ) ) {
583
-
584
  // Create the directory.
585
  mkdir( $dir_info['path'] );
586
-
587
  // Add an index file for security.
588
  file_put_contents( $dir_info['path'] . 'index.html', '' );
589
  }
@@ -592,7 +670,7 @@ final class FLBuilderModel {
592
  }
593
 
594
  /**
595
- * Returns an array of paths for the cache directory
596
  * of the current site.
597
  *
598
  * @since 1.0
@@ -603,7 +681,7 @@ final class FLBuilderModel {
603
  {
604
  $upload_info = self::get_upload_dir();
605
  $allowed = array( 'cache', 'icons' );
606
-
607
  // Make sure the dir name is allowed.
608
  if ( ! in_array( $name, $allowed ) ) {
609
  return false;
@@ -617,10 +695,10 @@ final class FLBuilderModel {
617
 
618
  // Create the cache dir if it doesn't exist.
619
  if( ! file_exists( $dir_info['path'] ) ) {
620
-
621
  // Create the directory.
622
  mkdir( $dir_info['path'] );
623
-
624
  // Add an index file for security.
625
  file_put_contents( $dir_info['path'] . 'index.html', '' );
626
  }
@@ -629,9 +707,9 @@ final class FLBuilderModel {
629
  }
630
 
631
  /**
632
- * Returns the version number to be applied to the query string
633
- * of a CSS or JS asset. If the builder is active a random hash
634
- * is returned to prevent caching, otherwise a hash of the post
635
  * update time is returned.
636
  *
637
  * @since 1.0
@@ -651,7 +729,7 @@ final class FLBuilderModel {
651
  }
652
 
653
  /**
654
- * Returns an array of paths for the CSS and JS assets
655
  * of the current post.
656
  *
657
  * @since 1.0
@@ -688,7 +766,7 @@ final class FLBuilderModel {
688
  }
689
 
690
  /**
691
- * Deletes either the preview, draft or live CSS and/or JS asset cache
692
  * for the current post based on the data returned from get_asset_info.
693
  * Both the CSS and JS asset cache will be delete if a type is not specified.
694
  *
@@ -702,7 +780,7 @@ final class FLBuilderModel {
702
  $types = $type ? array( $type ) : array( 'css', 'css_partial', 'js', 'js_partial' );
703
 
704
  foreach ( $types as $type ) {
705
-
706
  if ( isset( $info[ $type ] ) && file_exists( $info[ $type ] ) ) {
707
  unlink( $info[ $type ] );
708
  }
@@ -710,8 +788,8 @@ final class FLBuilderModel {
710
  }
711
 
712
  /**
713
- * Deletes preview, draft and live CSS/JS asset cache for the current
714
- * post. If a post ID is supplied, the asset cache will be deleted for
715
  * that post instead.
716
  *
717
  * @since 1.0
@@ -724,7 +802,7 @@ final class FLBuilderModel {
724
  $cache_dir = self::get_cache_dir();
725
 
726
  if ( $post_id ) {
727
-
728
  $paths = array(
729
  $cache_dir['path'] . $post_id . '-layout.css',
730
  $cache_dir['path'] . $post_id . '-layout-draft.css',
@@ -739,7 +817,7 @@ final class FLBuilderModel {
739
  $cache_dir['path'] . $post_id . '-layout-draft-partial.js',
740
  $cache_dir['path'] . $post_id . '-layout-preview-partial.js'
741
  );
742
-
743
  foreach ( $paths as $path ) {
744
  if ( file_exists( $path ) ) {
745
  unlink( $path );
@@ -759,8 +837,8 @@ final class FLBuilderModel {
759
  static public function delete_node_template_asset_cache( $post_id = false )
760
  {
761
  $posts = self::get_posts_with_global_node_template( $post_id );
762
-
763
- if ( ! empty( $posts ) ) {
764
  foreach( $posts as $post ) {
765
  self::delete_all_asset_cache( $post->ID );
766
  }
@@ -778,7 +856,7 @@ final class FLBuilderModel {
778
  $cache_dir = self::get_cache_dir();
779
  $css = glob( $cache_dir['path'] . '*.css' );
780
  $js = glob( $cache_dir['path'] . '*.js' );
781
-
782
  if ( is_array( $css ) ) {
783
  array_map( 'unlink', $css );
784
  }
@@ -789,7 +867,7 @@ final class FLBuilderModel {
789
 
790
  /**
791
  * Generates a unique id for a builder node such as a
792
- * row, column or module.
793
  *
794
  * @since 1.0
795
  * @return string
@@ -899,7 +977,7 @@ final class FLBuilderModel {
899
  }
900
  }
901
  }
902
-
903
  // Sort the nodes by position.
904
  uasort( $nodes, array( 'FLBuilderModel', 'order_nodes' ) );
905
 
@@ -926,20 +1004,20 @@ final class FLBuilderModel {
926
  static public function get_node_parent( $node_id = null, $status = null )
927
  {
928
  $parent = null;
929
-
930
  if ( is_object( $node_id ) ) {
931
  $node = $node_id;
932