PluginProbe
Block Animations, Motion & Scroll Effects – Ghost Kit / 3.7.2
Block Animations, Motion & Scroll Effects – Ghost Kit v3.7.2
3.7.2 3.7.1 3.7.0 3.6.1 trunk 1.6.3 2.25.0 3.3.0 3.3.1 3.3.2 3.3.3 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.5.0 3.5.1 3.6.0
← All changes | class-ghost-kit.php +436 -417 1.6.33.7.2 View file →
@@ -1,11 +1,12 @@
1 1 <?php
2 2 /**
3 - * Plugin Name: GhostKit
4 - * Description: Blocks collection and extensions for Gutenberg
5 - * Version: 1.6.3
6 - * Author: nK
7 - * Author URI: https://nkdev.info
3 + * Plugin Name: Ghost Kit
4 + * Description: Animate WordPress blocks with reveal, scroll, mouse and loop effects.
5 + * Version: 3.7.2
6 + * Plugin URI: https://www.ghostkit.io/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=byline
7 + * Author: Ghost Kit Team
8 + * Author URI: https://www.ghostkit.io/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=byline
8 9 * License: GPLv2 or later
9 10 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
10 11 * Text Domain: ghostkit
11 12 *
@@ -12,480 +13,498 @@
12 13 * @package ghostkit
13 14 */
14 15
15 16 if ( ! defined( 'ABSPATH' ) ) {
16 - exit;
17 + exit;
17 18 }
18 19
19 -/**
20 - * GhostKit Class
20 +/*
21 + * Ghost Kit Pro carries its own copy of this core, so only one of the two may run.
22 + * Which copy PHP reaches first depends on the order WordPress includes plugins in,
23 + * and that order is not ours to pick: network-activated plugins come before
24 + * site-activated ones, and a third party can reorder `active_plugins`. So the
25 + * standalone plugin steps aside on its own whenever the Pro plugin is active,
26 + * before it defines anything at all.
27 + *
28 + * Only the activated plugin steps aside. The copy inside the Pro plugin, and any
29 + * copy embedded in a theme or another plugin, is not in the list below and keeps
30 + * loading as before.
21 31 */
22 -class GhostKit {
32 +$gkt_active_plugins = (array) get_option( 'active_plugins', array() );
23 33
24 - /**
25 - * The single class instance.
26 - *
27 - * @var $_instance
28 - */
29 - private static $_instance = null;
34 +if ( is_multisite() ) {
35 + $gkt_active_plugins = array_merge(
36 + $gkt_active_plugins,
37 + array_keys( (array) get_site_option( 'active_sitewide_plugins', array() ) )
38 + );
39 +}
30 40
31 - /**
32 - * Path to the plugin directory
33 - *
34 - * @var $plugin_path
35 - */
36 - public $plugin_path;
41 +if (
42 + in_array( plugin_basename( __FILE__ ), $gkt_active_plugins, true ) &&
43 + in_array( 'ghostkit-pro/class-ghost-kit-pro.php', $gkt_active_plugins, true ) &&
44 + // `active_plugins` goes on naming a plugin whose directory was removed by hand
45 + // and WordPress simply skips it, so stepping aside for one of those would leave
46 + // the site with neither plugin.
47 + file_exists( WP_PLUGIN_DIR . '/ghostkit-pro/class-ghost-kit-pro.php' )
48 +) {
49 + unset( $gkt_active_plugins );
50 + return;
51 +}
37 52
38 - /**
39 - * URL to the plugin directory
40 - *
41 - * @var $plugin_url
42 - */
43 - public $plugin_url;
53 +unset( $gkt_active_plugins );
44 54
45 - /**
46 - * Plugin name
47 - *
48 - * @var $plugin_name
49 - */
50 - public $plugin_name;
55 +if ( ! defined( 'GHOSTKIT_VERSION' ) ) {
56 + define( 'GHOSTKIT_VERSION', '3.7.2' );
57 +}
51 58
52 - /**
53 - * Plugin version
54 - *
55 - * @var $plugin_version
56 - */
57 - public $plugin_version;
59 +if ( ! class_exists( 'GhostKit' ) ) :
60 + /**
61 + * GhostKit Class
62 + */
63 + class GhostKit {
58 64
59 - /**
60 - * Plugin slug
61 - *
62 - * @var $plugin_slug
63 - */
64 - public $plugin_slug;
65 + /**
66 + * The single class instance.
67 + *
68 + * @var $instance
69 + */
70 + private static $instance = null;
65 71
66 - /**
67 - * Plugin name sanitized
68 - *
69 - * @var $plugin_name_sanitized
70 - */
71 - public $plugin_name_sanitized;
72 + /**
73 + * Path to the plugin directory
74 + *
75 + * @var $plugin_path
76 + */
77 + public $plugin_path;
72 78
73 - /**
74 - * GhostKit constructor.
75 - */
76 - public function __construct() {
77 - /* We do nothing here! */
78 - }
79 + /**
80 + * URL to the plugin directory
81 + *
82 + * @var $plugin_url
83 + */
84 + public $plugin_url;
79 85
80 - /**
81 - * Main Instance
82 - * Ensures only one instance of this class exists in memory at any one time.
83 - */
84 - public static function instance() {
85 - if ( is_null( self::$_instance ) ) {
86 - self::$_instance = new self();
87 - self::$_instance->init_options();
88 - self::$_instance->init_hooks();
89 - }
90 - return self::$_instance;
91 - }
86 + /**
87 + * Plugin name
88 + *
89 + * @var $plugin_name
90 + */
91 + public $plugin_name;
92 92
93 - /**
94 - * Init options
95 - */
96 - public function init_options() {
97 - $this->plugin_path = plugin_dir_path( __FILE__ );
98 - $this->plugin_url = plugin_dir_url( __FILE__ );
93 + /**
94 + * Plugin version
95 + *
96 + * @var $plugin_version
97 + */
98 + public $plugin_version;
99 99
100 - // load textdomain.
101 - load_plugin_textdomain( 'ghostkit', false, basename( dirname( __FILE__ ) ) . '/languages' );
100 + /**
101 + * Plugin slug
102 + *
103 + * @var $plugin_slug
104 + */
105 + public $plugin_slug;
102 106
103 - // additional blocks php.
104 - require_once( $this->plugin_path . 'blocks/index.php' );
107 + /**
108 + * Plugin name sanitized
109 + *
110 + * @var $plugin_name_sanitized
111 + */
112 + public $plugin_name_sanitized;
105 113
106 - // rest.
107 - require_once( $this->plugin_path . 'classes/class-rest.php' );
114 + /**
115 + * GhostKit constructor.
116 + */
117 + public function __construct() {
118 + /* We do nothing here! */
119 + }
108 120
109 - // reusable widget.
110 - require_once( $this->plugin_path . 'classes/class-reusable-widget.php' );
111 - }
121 + /**
122 + * Main Instance
123 + * Ensures only one instance of this class exists in memory at any one time.
124 + */
125 + public static function instance() {
126 + if ( is_null( self::$instance ) ) {
127 + self::$instance = new self();
128 + self::$instance->init_options();
129 + self::$instance->init_hooks();
130 + }
131 + return self::$instance;
132 + }
112 133
134 + /**
135 + * Init options
136 + */
137 + public function init_options() {
138 + $this->plugin_path = plugin_dir_path( __FILE__ );
139 + $this->plugin_url = plugin_dir_url( __FILE__ );
113 140
114 - /**
115 - * Init hooks
116 - */
117 - public function init_hooks() {
118 - add_action( 'admin_init', array( $this, 'admin_init' ) );
141 + require_once $this->plugin_path . 'settings/index.php';
142 + require_once $this->plugin_path . 'gutenberg/index.php';
119 143
120 - add_action( 'init', array( $this, 'add_custom_fields_support' ), 100 );
144 + require_once $this->plugin_path . 'classes/class-rest.php';
145 + require_once $this->plugin_path . 'classes/class-parse-blocks.php';
146 + require_once $this->plugin_path . 'classes/class-assets-detector.php';
147 + require_once $this->plugin_path . 'classes/class-assets.php';
148 + require_once $this->plugin_path . 'classes/class-reusable-widget.php';
149 + require_once $this->plugin_path . 'classes/class-icons.php';
150 + require_once $this->plugin_path . 'classes/class-shapes.php';
151 + require_once $this->plugin_path . 'classes/class-typography.php';
152 + require_once $this->plugin_path . 'classes/class-fonts.php';
153 + require_once $this->plugin_path . 'classes/class-templates.php';
154 + require_once $this->plugin_path . 'classes/class-breakpoints.php';
155 + require_once $this->plugin_path . 'classes/class-ask-review.php';
156 + require_once $this->plugin_path . 'classes/class-deactivate-duplicate-plugin.php';
121 157
122 - add_action( 'save_post', array( $this, 'parse_styles_from_blocks' ) );
123 - add_action( 'wp_enqueue_scripts', array( $this, 'add_styles_from_blocks' ), 100 );
158 + require_once $this->plugin_path . 'gutenberg/utils/encode-decode/index.php';
159 + require_once $this->plugin_path . 'gutenberg/extend/index.php';
124 160
125 - // include blocks.
126 - // work only if Gutenberg available.
127 - if ( function_exists( 'register_block_type' ) ) {
128 - add_action( 'init', array( $this, 'register_scripts' ) );
161 + // 3rd.
162 + require_once $this->plugin_path . 'classes/3rd/class-astra.php';
163 + require_once $this->plugin_path . 'classes/3rd/class-page-builder-framework.php';
164 + require_once $this->plugin_path . 'classes/3rd/class-blocksy.php';
165 + require_once $this->plugin_path . 'classes/3rd/class-rank-math.php';
129 166
130 - // add GhostKit blocks category.
131 - add_filter( 'block_categories', array( $this, 'block_categories' ), 9 );
167 + // Migration.
168 + require_once $this->plugin_path . 'classes/class-migration.php';
169 + }
132 170
133 - // we need to enqueue the main script earlier to let 3rd-party plugins add custom styles support.
134 - add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ), 9 );
135 - add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_block_assets' ) );
136 - }
137 - }
171 + /**
172 + * Init hooks
173 + */
174 + public function init_hooks() {
175 + add_action( 'admin_init', array( $this, 'admin_init' ) );
138 176
139 - /**
140 - * Register GhostKit blocks category
141 - *
142 - * @param array $categories - available categories.
143 - * @return array
144 - */
145 - public function block_categories( $categories ) {
146 - return array_merge(
147 - $categories,
148 - array(
149 - array(
150 - 'slug' => 'ghostkit',
151 - 'title' => __( 'GhostKit', 'ghostkit' ),
152 - ),
153 - )
154 - );
155 - }
177 + add_action( 'init', array( $this, 'init_hook' ) );
156 178
157 - /**
158 - * Register scripts.
159 - */
160 - public function register_scripts() {
161 - // FontAwesome.
162 - if ( apply_filters( 'gkt_enqueue_plugin_font_awesome', true ) ) {
163 - wp_register_script( 'font-awesome-v4-shims', plugins_url( 'assets/vendor/font-awesome/v4-shims.min.js', __FILE__ ), array(), '5.2.0' );
164 - wp_register_script( 'font-awesome', plugins_url( 'assets/vendor/font-awesome/all.min.js', __FILE__ ), array( 'font-awesome-v4-shims' ), '5.2.0' );
165 - }
179 + add_action( 'init', array( $this, 'add_custom_fields_support' ), 100 );
166 180
167 - // VideoWorker.
168 - if ( apply_filters( 'gkt_enqueue_plugin_video_worker', true ) ) {
169 - wp_register_script( 'video-worker', plugins_url( 'assets/vendor/video-worker/dist/video-worker.js', __FILE__ ), array(), '1.1.2' );
170 - }
181 + add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'add_go_pro_link_plugins_page' ) );
171 182
172 - // Object Fit Images.
173 - if ( apply_filters( 'gkt_enqueue_plugin_object_fit_images', true ) ) {
174 - wp_register_script( 'object-fit-images', plugins_url( 'assets/vendor/object-fit-images/ofi.min.js', __FILE__ ), array(), '3.2.3', true );
175 - }
183 + add_action( 'wp_enqueue_scripts', array( $this, 'js_translation' ), 11 );
184 + add_action( 'enqueue_block_editor_assets', array( $this, 'js_translation_editor' ) );
176 185
177 - // Swiper.
178 - if ( apply_filters( 'gkt_enqueue_plugin_swiper', true ) ) {
179 - wp_register_style( 'swiper', plugins_url( 'assets/vendor/swiper/css/swiper.css', __FILE__ ), array(), '4.3.3' );
180 - wp_register_script( 'swiper', plugins_url( 'assets/vendor/swiper/js/swiper.min.js', __FILE__ ), array(), '4.3.3', true );
181 - }
186 + // add Ghost Kit blocks category.
187 + add_filter( 'block_categories_all', array( $this, 'block_categories_all' ), 9999 );
182 188
183 - // GistEmbed.
184 - if ( apply_filters( 'gkt_enqueue_plugin_gist_embed', true ) ) {
185 - wp_register_script( 'gist-embed', plugins_url( 'assets/vendor/gist-embed/gist-embed.min.js', __FILE__ ), array( 'jquery' ), '2.7.1', true );
186 - }
189 + // we need to enqueue the main script earlier to let 3rd-party plugins add custom styles support.
190 + add_action( 'enqueue_block_assets', array( $this, 'enqueue_block_assets' ), 9 );
187 191
188 - // ScrollReveal.
189 - if ( apply_filters( 'gkt_enqueue_plugin_scrollreveal', true ) ) {
190 - wp_register_script( 'scrollreveal', plugins_url( 'assets/vendor/scrollreveal/scrollreveal.min.js', __FILE__ ), array(), '4.0.2', true );
191 - }
192 + // add support for excerpts to some blocks.
193 + add_filter( 'excerpt_allowed_blocks', array( $this, 'excerpt_allowed_blocks' ) );
192 194
193 - // Get all sidebars.
194 - $sidebars = false;
195 - if ( ! empty( $GLOBALS['wp_registered_sidebars'] ) ) {
196 - foreach ( $GLOBALS['wp_registered_sidebars'] as $k => $sidebar ) {
197 - $sidebars[ $k ] = array(
198 - 'id' => $sidebar['id'],
199 - 'name' => $sidebar['name'],
200 - );
201 - }
202 - }
195 + // add support for additional mimes.
196 + add_filter( 'upload_mimes', array( $this, 'upload_mimes' ), 100 );
197 + add_filter( 'wp_check_filetype_and_ext', array( $this, 'wp_check_filetype_and_ext' ), 100, 3 );
198 + }
203 199
204 - // helper script.
205 - wp_register_script(
206 - 'ghostkit-helper',
207 - plugins_url( 'assets/js/helper.min.js', __FILE__ ),
208 - array( 'jquery' ),
209 - filemtime( plugin_dir_path( __FILE__ ) . 'assets/js/helper.min.js' )
210 - );
211 - $default_variant = array(
212 - 'default' => array(
213 - 'title' => esc_html__( 'Default', 'ghostkit' ),
214 - ),
215 - );
200 + /**
201 + * JS translation.
202 + */
203 + public function js_translation() {
204 + if ( ! function_exists( 'wp_set_script_translations' ) ) {
205 + return;
206 + }
216 207
217 - // Google Maps prepare localization as in WordPress settings.
218 - $gmaps_locale = get_locale();
219 - $gmaps_suffix = '.com';
220 - switch ( $gmaps_locale ) {
221 - case 'he_IL':
222 - // Hebrew correction.
223 - $gmaps_locale = 'iw';
224 - break;
225 - case 'zh_CN':
226 - // Chinese integration.
227 - $gmaps_suffix = '.cn';
228 - break;
229 - }
230 - $gmaps_locale = substr( $gmaps_locale, 0, 2 );
208 + wp_set_script_translations( 'ghostkit-block-countdown', 'ghostkit', plugin_dir_path( __FILE__ ) . '/languages' );
209 + }
231 210
232 - wp_localize_script( 'ghostkit-helper', 'ghostkitVariables', array(
233 - // TODO: Move this to plugin options (part 1).
234 - 'media_sizes' => array(
235 - 'sm' => 576,
236 - 'md' => 768,
237 - 'lg' => 992,
238 - 'xl' => 1200,
239 - ),
240 - 'googleMapsAPIKey' => get_option( 'ghostkit_google_maps_api_key' ),
241 - 'googleMapsAPIUrl' => 'https://maps.googleapis' . $gmaps_suffix . '/maps/api/js?v=3.exp&language=' . esc_attr( $gmaps_locale ),
242 - 'googleMapsLibrary' => apply_filters( 'gkt_enqueue_plugin_gmaps', true ) ? array(
243 - 'url' => plugins_url( 'assets/vendor/gmaps/gmaps.min.js', __FILE__ ) . '?ver=0.4.25',
244 - ) : false,
245 - 'sidebars' => $sidebars,
246 - 'variants' => array(
247 - 'accordion' => array_merge( $default_variant, apply_filters( 'gkt_accordion_variants', array() ) ),
248 - 'accordion_item' => array_merge( $default_variant, apply_filters( 'gkt_accordion_item_variants', array() ) ),
249 - 'alert' => array_merge( $default_variant, apply_filters( 'gkt_alert_variants', array() ) ),
250 - 'button_wrapper' => array_merge( $default_variant, apply_filters( 'gkt_button_wrapper_variants', array() ) ),
251 - 'button' => array_merge( $default_variant, apply_filters( 'gkt_button_variants', array() ) ),
252 - 'carousel' => array_merge( $default_variant, apply_filters( 'gkt_carousel_variants', array() ) ),
253 - 'carousel_slide' => array_merge( $default_variant, apply_filters( 'gkt_carousel_slide_variants', array() ) ),
254 - 'changelog' => array_merge( $default_variant, apply_filters( 'gkt_changelog_variants', array() ) ),
255 - 'counter_box' => array_merge( $default_variant, apply_filters( 'gkt_counter_box_variants', array() ) ),
256 - 'divider' => array_merge( $default_variant, apply_filters( 'gkt_divider_variants', array() ) ),
257 - 'gist' => array_merge( $default_variant, apply_filters( 'gkt_gist_variants', array() ) ),
258 - 'google_maps' => array_merge( $default_variant, apply_filters( 'gkt_google_maps_variants', array() ) ),
259 - 'grid' => array_merge( $default_variant, apply_filters( 'gkt_grid_variants', array() ) ),
260 - 'grid_column' => array_merge( $default_variant, apply_filters( 'gkt_grid_column_variants', array() ) ),
261 - 'icon_box' => array_merge( $default_variant, apply_filters( 'gkt_icon_box_variants', array() ) ),
262 - 'instagram' => array_merge( $default_variant, apply_filters( 'gkt_instagram_variants', array() ) ),
263 - 'pricing_table' => array_merge( $default_variant, apply_filters( 'gkt_pricing_table_variants', array() ) ),
264 - 'pricing_table_item' => array_merge( $default_variant, apply_filters( 'gkt_pricing_table_item_variants', array() ) ),
265 - 'progress' => array_merge( $default_variant, apply_filters( 'gkt_progress_variants', array() ) ),
266 - 'tabs' => array_merge( $default_variant, apply_filters( 'gkt_tabs_variants', array() ) ),
267 - 'tabs_tab' => array_merge( $default_variant, apply_filters( 'gkt_tabs_tab_variants', array() ) ),
268 - 'testimonial' => array_merge( $default_variant, apply_filters( 'gkt_testimonial_variants', array() ) ),
269 - 'twitter' => array_merge( $default_variant, apply_filters( 'gkt_twitter_variants', array() ) ),
270 - 'video' => array_merge( $default_variant, apply_filters( 'gkt_video_variants', array() ) ),
271 - ),
272 - 'admin_url' => admin_url(),
273 - ) );
274 - }
211 + /**
212 + * JS translation for editor.
213 + */
214 + public function js_translation_editor() {
215 + if ( ! function_exists( 'wp_set_script_translations' ) ) {
216 + return;
217 + }
275 218
276 - /**
277 - * Enqueue editor assets
278 - */
279 - public function enqueue_block_editor_assets() {
280 - $css_deps = array();
281 - $js_deps = array( 'ghostkit-helper', 'wp-editor', 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-edit-post', 'wp-compose', 'underscore', 'wp-components' );
219 + wp_set_script_translations( 'ghostkit-editor', 'ghostkit', plugin_dir_path( __FILE__ ) . '/languages' );
220 + wp_set_script_translations( 'ghostkit-settings', 'ghostkit', plugin_dir_path( __FILE__ ) . '/languages' );
221 + }
282 222
283 - // FontAwesome.
284 - if ( apply_filters( 'gkt_enqueue_plugin_font_awesome', true ) ) {
285 - $js_deps[] = 'font-awesome';
286 - }
223 + /**
224 + * Register Ghost Kit blocks category
225 + *
226 + * @param array $categories - available categories.
227 + * @return array
228 + */
229 + public function block_categories_all( $categories ) {
230 + return array_merge(
231 + array(
232 + array(
233 + 'slug' => 'ghostkit',
234 + 'title' => __( 'Ghost Kit', 'ghostkit' ),
235 + ),
236 + ),
237 + $categories
238 + );
239 + }
287 240
288 - // VideoWorker.
289 - if ( apply_filters( 'gkt_enqueue_plugin_video_worker', true ) ) {
290 - $js_deps[] = 'video-worker';
291 - }
241 + /**
242 + * Enqueue editor assets
243 + */
244 + public function enqueue_block_assets() {
245 + if ( ! is_admin() ) {
246 + return;
247 + }
292 248
293 - // GistEmbed.
294 - if ( apply_filters( 'gkt_enqueue_plugin_gist_embed', true ) ) {
295 - $js_deps[] = 'gist-embed';
296 - }
249 + global $current_screen;
297 250
298 - // GhostKit.
299 - wp_enqueue_style(
300 - 'ghostkit-editor',
301 - plugins_url( 'assets/admin/css/style.min.css', __FILE__ ),
302 - $css_deps,
303 - filemtime( plugin_dir_path( __FILE__ ) . 'assets/admin/css/style.min.css' )
304 - );
305 - wp_enqueue_script(
306 - 'ghostkit-editor',
307 - plugins_url( 'blocks/index.min.js', __FILE__ ),
308 - $js_deps,
309 - filemtime( plugin_dir_path( __FILE__ ) . 'blocks/index.min.js' )
310 - );
311 - }
251 + $css_deps = array();
252 + $js_deps = array( 'ghostkit-helper' );
312 253
313 - /**
314 - * Enqueue editor frontend assets
315 - */
316 - public function enqueue_block_assets() {
317 - $css_deps = array();
318 - $js_deps = array( 'jquery', 'ghostkit-helper' );
254 + // Ivent.
255 + if ( apply_filters( 'gkt_enqueue_plugin_ivent', true ) ) {
256 + $js_deps[] = 'ivent';
257 + }
319 258
320 - // FontAwesome.
321 - if ( apply_filters( 'gkt_enqueue_plugin_font_awesome', true ) ) {
322 - $js_deps[] = 'font-awesome';
323 - }
259 + // Motion.
260 + if ( apply_filters( 'gkt_enqueue_plugin_motion', true ) ) {
261 + $js_deps[] = 'motion';
262 + }
324 263
325 - // VideoWorker.
326 - if ( apply_filters( 'gkt_enqueue_plugin_video_worker', true ) ) {
327 - $js_deps[] = 'video-worker';
328 - }
264 + // Jarallax.
265 + if ( apply_filters( 'gkt_enqueue_plugin_jarallax', true ) ) {
266 + $js_deps[] = 'jarallax';
267 + $js_deps[] = 'jarallax-video';
268 + }
329 269
330 - // Object Fit Images.
331 - if ( apply_filters( 'gkt_enqueue_plugin_object_fit_images', true ) ) {
332 - $js_deps[] = 'object-fit-images';
333 - }
270 + // Luxon.
271 + if ( apply_filters( 'gkt_enqueue_plugin_luxon', true ) ) {
272 + $js_deps[] = 'luxon';
273 + }
334 274
335 - // Swiper.
336 - if ( apply_filters( 'gkt_enqueue_plugin_swiper', true ) ) {
337 - $css_deps[] = 'swiper';
338 - $js_deps[] = 'swiper';
339 - }
275 + // Lottie Player.
276 + if ( apply_filters( 'gkt_enqueue_plugin_lottie_player', true ) ) {
277 + $js_deps[] = 'lottie-player';
278 + }
340 279
341 - // GistEmbed.
342 - if ( apply_filters( 'gkt_enqueue_plugin_gist_embed', true ) ) {
343 - $js_deps[] = 'gist-embed';
344 - }
280 + // GistEmbed.
281 + if ( apply_filters( 'gkt_enqueue_plugin_gist_simple', true ) ) {
282 + $css_deps[] = 'gist-simple';
283 + $js_deps[] = 'gist-simple';
284 + }
345 285
346 - // ScrollReveal.
347 - if ( apply_filters( 'gkt_enqueue_plugin_scrollreveal', true ) ) {
348 - $js_deps[] = 'scrollreveal';
349 - }
286 + // In block metadata, many Ghost Kit blocks declare `style: ["ghostkit", ...]`.
287 + // Because of this, WordPress auto-enqueues the `ghostkit` style handle for those blocks
288 + // in every context where blocks are rendered, including the editor.
289 + //
290 + // `ghostkit` is our frontend stylesheet (`build/gutenberg/style.css`), while editor UI
291 + // is styled by `ghostkit-editor` (`build/gutenberg/editor.css`). Loading both in editor
292 + // causes conflicts (for example, frontend Display extension rules can hide editor blocks).
293 + //
294 + // To keep block dependency chains intact without editing all block.json files, we override
295 + // only the `ghostkit` handle in admin and make it an alias that depends on `ghostkit-editor`.
296 + // Result:
297 + // - frontend keeps using real `ghostkit` styles;
298 + // - editor resolves `ghostkit` dependencies to editor styles, avoiding CSS conflicts.
299 + if ( wp_style_is( 'ghostkit', 'registered' ) ) {
300 + wp_deregister_style( 'ghostkit' );
301 + }
302 + wp_register_style( 'ghostkit', false, array( 'ghostkit-editor' ), GHOSTKIT_VERSION );
350 303
351 - // GhostKit.
352 - wp_enqueue_style(
353 - 'ghostkit',
354 - plugins_url( 'blocks/style.min.css', __FILE__ ),
355 - $css_deps,
356 - filemtime( plugin_dir_path( __FILE__ ) . 'blocks/style.min.css' )
357 - );
358 - wp_enqueue_script(
359 - 'ghostkit',
360 - plugins_url( 'assets/js/script.min.js', __FILE__ ),
361 - $js_deps,
362 - filemtime( plugin_dir_path( __FILE__ ) . 'assets/js/script.min.js' )
363 - );
364 - }
304 + // Ghost Kit.
305 + GhostKit_Assets::enqueue_style(
306 + 'ghostkit-editor',
307 + 'build/gutenberg/editor',
308 + $css_deps,
309 + filemtime( plugin_dir_path( __FILE__ ) . 'build/gutenberg/editor.css' )
310 + );
311 + wp_style_add_data( 'ghostkit-editor', 'rtl', 'replace' );
365 312
366 - /**
367 - * Init variables
368 - */
369 - public function admin_init() {
370 - // get current plugin data.
371 - $data = get_plugin_data( __FILE__ );
372 - $this->plugin_name = $data['Name'];
373 - $this->plugin_version = $data['Version'];
374 - $this->plugin_slug = plugin_basename( __FILE__, '.php' );
375 - $this->plugin_name_sanitized = basename( __FILE__, '.php' );
376 - }
313 + // Since WordPress 7.1 the post editor canvas is always iframed, and core collects
314 + // the iframe assets by running `enqueue_block_assets` a second time with
315 + // `should_load_block_editor_scripts_and_styles` forced to false.
316 + // The editor bundles belong to the editor chrome only - loading them in the canvas
317 + // would boot a second copy of the block editor inside the iframe. The vendor
318 + // libraries, on the other hand, are needed inside the canvas to render block previews
319 + // (for example the `lottie-player` custom element, which is registered per window).
320 + if ( ! wp_should_load_block_editor_scripts_and_styles() ) {
321 + foreach ( $js_deps as $dep ) {
322 + wp_enqueue_script( $dep );
323 + }
377 324
378 - /**
379 - * Add support for 'custom-fields' for all post types.
380 - * Required by Customizer and Custom CSS blocks.
381 - */
382 - public function add_custom_fields_support() {
383 - $available_post_types = get_post_types( array(
384 - 'show_ui' => true,
385 - ), 'object' );
325 + return;
326 + }
386 327
387 - foreach ( $available_post_types as $post_type ) {
388 - if ( 'attachment' !== $post_type->name ) {
389 - add_post_type_support( $post_type->name, 'custom-fields' );
390 - }
391 - }
392 - }
328 + GhostKit_Assets::enqueue_script(
329 + 'ghostkit-editor',
330 + 'build/gutenberg/index',
331 + $js_deps
332 + );
393 333
394 - /**
395 - * Parse styles from blocks and save it to the post meta.
396 - *
397 - * @param int $post_id - current post id.
398 - */
399 - public function parse_styles_from_blocks( $post_id ) {
400 - if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
401 - return;
402 - }
403 - if ( ! current_user_can( 'edit_post', $post_id ) ) {
404 - return;
405 - }
334 + // Load plugins in editor only (skip legacy Widgets screen).
335 + if ( ! isset( $current_screen->id ) || 'widgets' !== $current_screen->id ) {
336 + GhostKit_Assets::enqueue_script(
337 + 'ghostkit-editor-plugins',
338 + 'build/gutenberg/plugins',
339 + array( 'ghostkit-editor' )
340 + );
341 + }
342 + }
406 343
407 - $post = get_post( $post_id );
344 + /**
345 + * Excerpt allowed wrapper blocks.
346 + *
347 + * @param array $blocks - allowed blocks.
348 + * @return array
349 + */
350 + public function excerpt_allowed_blocks( $blocks ) {
351 + return array_merge(
352 + $blocks,
353 + array(
354 + 'ghostkit/accordion',
355 + 'ghostkit/accordion-item',
356 + 'ghostkit/alert',
357 + 'ghostkit/button',
358 + 'ghostkit/carousel',
359 + 'ghostkit/carousel-single',
360 + 'ghostkit/changelog',
361 + 'ghostkit/counter-box',
362 + 'ghostkit/grid',
363 + 'ghostkit/grid-column',
364 + 'ghostkit/icon-box',
365 + 'ghostkit/pricing-table',
366 + 'ghostkit/pricing-table-item',
367 + 'ghostkit/tabs-v2',
368 + 'ghostkit/tabs-tab-v2',
369 + 'ghostkit/testimonial',
370 + )
371 + );
372 + }
408 373
409 - if ( ! $post->post_content ) {
410 - return;
411 - }
374 + /**
375 + * Allow JSON uploads
376 + *
377 + * @param array $mimes supported mimes.
378 + *
379 + * @return array
380 + */
381 + public function upload_mimes( $mimes ) {
382 + if ( ! isset( $mimes['json'] ) ) {
383 + $mimes['json'] = 'application/json';
384 + }
412 385
413 - if ( class_exists( 'DOMDocument' ) ) {
414 - $css = '';
415 - $dom = new DOMDocument();
416 - @$dom->loadHTML( $post->post_content );
417 - foreach ( $dom->getElementsByTagName( '*' ) as $node ) {
418 - $styles = $node->getAttribute( 'data-ghostkit-styles' );
419 - if ( $styles ) {
420 - $css .= ' ' . $styles;
421 - }
422 - }
386 + return $mimes;
387 + }
423 388
424 - if ( empty( $css ) || ! $css ) {
425 - delete_post_meta( $post_id, '_ghostkit_blocks_custom_css' );
426 - } else {
427 - // TODO: Move this to plugin options (part 2).
428 - $vars = array(
429 - 'media_sm' => '(max-width: 576px)',
430 - 'media_md' => '(max-width: 768px)',
431 - 'media_lg' => '(max-width: 992px)',
432 - 'media_xl' => '(max-width: 1200px)',
433 - );
389 + /**
390 + * Allow JSON file uploads
391 + *
392 + * @param array $data File data.
393 + * @param array $file File object.
394 + * @param string $filename File name.
395 + *
396 + * @return array
397 + */
398 + public function wp_check_filetype_and_ext( $data, $file, $filename ) {
399 + $ext = isset( $data['ext'] ) ? $data['ext'] : '';
434 400
435 - foreach ( $vars as $k => $var ) {
436 - $css = preg_replace( "/#{ghostkitvar:$k}/", $var, $css );
437 - }
401 + if ( ! $ext ) {
402 + $exploded = explode( '.', $filename );
403 + $ext = strtolower( end( $exploded ) );
404 + }
438 405
439 - update_post_meta( $post_id, '_ghostkit_blocks_custom_css', $css );
440 - }
441 - }
442 - }
406 + if ( 'json' === $ext ) {
407 + $data['type'] = 'application/json';
408 + $data['ext'] = 'json';
409 + }
443 410
444 - /**
445 - * Add styles from blocks to the head section.
446 - *
447 - * @param int $post_id - current post id.
448 - */
449 - public function add_styles_from_blocks( $post_id ) {
450 - if ( ! is_singular() ) {
451 - return;
452 - }
453 - if ( ! $post_id ) {
454 - $post_id = get_the_ID();
455 - }
411 + return $data;
412 + }
456 413
457 - if ( $post_id ) {
458 - $css = get_post_meta( $post_id, '_ghostkit_blocks_custom_css', true );
459 - $custom_css = get_post_meta( $post_id, 'ghostkit_custom_css', true );
414 + /**
415 + * Init variables
416 + */
417 + public function admin_init() {
418 + // get current plugin data.
419 + $data = get_plugin_data( __FILE__ );
420 + $this->plugin_name = $data['Name'];
421 + $this->plugin_version = $data['Version'];
422 + $this->plugin_slug = plugin_basename( __FILE__ );
423 + $this->plugin_name_sanitized = basename( __FILE__, '.php' );
424 + }
460 425
461 - if ( ! empty( $css ) ) {
462 - $custom_css_handle = 'ghostkit-blocks-custom-css';
463 - $css = wp_kses( $css, array( '\'', '\"' ) );
464 - $css = str_replace( '&gt;', '>', $css );
426 + /**
427 + * Init hook
428 + */
429 + public function init_hook() {
430 + load_plugin_textdomain( 'ghostkit', false, plugin_dir_path( __FILE__ ) . '/languages' );
431 + }
465 432
466 - wp_register_style( $custom_css_handle, false );
467 - wp_enqueue_style( $custom_css_handle );
468 - wp_add_inline_style( $custom_css_handle, $css );
469 - }
470 - if ( ! empty( $custom_css ) ) {
471 - $custom_css_handle = 'ghostkit-custom-css';
472 - $css = wp_kses( $custom_css, array( '\'', '\"' ) );
473 - $css = str_replace( '&gt;', '>', $css );
433 + /**
434 + * Add support for 'custom-fields' for all post types.
435 + * Required by Customizer and Custom CSS blocks.
436 + */
437 + public function add_custom_fields_support() {
438 + $available_post_types = get_post_types(
439 + array(
440 + 'show_ui' => true,
441 + ),
442 + 'object'
443 + );
474 444
475 - wp_register_style( $custom_css_handle, false );
476 - wp_enqueue_style( $custom_css_handle );
477 - wp_add_inline_style( $custom_css_handle, $css );
478 - }
479 - }
480 - }
481 -}
445 + foreach ( $available_post_types as $post_type ) {
446 + if ( 'attachment' !== $post_type->name ) {
447 + add_post_type_support( $post_type->name, 'custom-fields' );
448 + }
449 + }
450 + }
482 451
483 -/**
484 - * Function works with the GhostKit class instance
485 - *
486 - * @return object GhostKit
487 - */
488 -function ghostkit() {
489 - return GhostKit::instance();
490 -}
491 -add_action( 'plugins_loaded', 'ghostkit' );
452 + /**
453 + * Equivalent of GHOSTKIT.replaceVars method.
454 + *
455 + * @param string $str styles string.
456 + * @return string string with replaced vars.
457 + */
458 + public function replace_vars( $str ) {
459 + $breakpoints = GhostKit_Breakpoints::get_breakpoints();
460 + // TODO: Due to different formats in scss and assets there is an offset.
461 + $vars = array(
462 + 'media_sm' => '(max-width: ' . $breakpoints['xs'] . 'px)',
463 + 'media_md' => '(max-width: ' . $breakpoints['sm'] . 'px)',
464 + 'media_lg' => '(max-width: ' . $breakpoints['md'] . 'px)',
465 + 'media_xl' => '(max-width: ' . $breakpoints['lg'] . 'px)',
466 + );
467 +
468 + foreach ( $vars as $k => $var ) {
469 + $str = preg_replace( "/#{ghostkitvar:$k}/", $var, $str );
470 + }
471 +
472 + return $str;
473 + }
474 +
475 + /**
476 + * Add Go Pro link to plugins page.
477 + *
478 + * @param array $links - available links.
479 + *
480 + * @return array
481 + */
482 + public function add_go_pro_link_plugins_page( $links ) {
483 + return array_merge(
484 + $links,
485 + array(
486 + '<a target="_blank" href="admin.php?page=ghostkit_go_pro&utm_medium=plugins_list">' . esc_html__( 'Go Pro', 'ghostkit' ) . '</a>',
487 + )
488 + );
489 + }
490 +
491 + /**
492 + * Get Go Pro link
493 + *
494 + * @return string
495 + */
496 + public function go_pro_link() {
497 + return 'https://www.ghostkit.io/pricing/';
498 + }
499 + }
500 +
501 + /**
502 + * Function works with the GhostKit class instance
503 + *
504 + * @return object GhostKit
505 + */
506 + function ghostkit() {
507 + return GhostKit::instance();
508 + }
509 + add_action( 'plugins_loaded', 'ghostkit' );
510 +endif;