PluginProbe
Block Animations, Motion & Scroll Effects – Ghost Kit / 3.7.1
Block Animations, Motion & Scroll Effects – Ghost Kit v3.7.1
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
ghostkit / class-ghost-kit.php

class-ghost-kit.php in Block Animations, Motion & Scroll Effects – Ghost Kit 3.7.1, at class-ghost-kit.php

515 lines 14.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Ghost Kit
4 * Description: Page Builder Blocks and Extensions for Gutenberg
5 * Version: 3.7.1
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
9 * License: GPLv2 or later
10 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
11 * Text Domain: ghostkit
12 *
13 * @package ghostkit
14 */
15
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit;
18 }
19
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.
31 */
32 $gkt_active_plugins = (array) get_option( 'active_plugins', array() );
33
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 }
40
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 }
52
53 unset( $gkt_active_plugins );
54
55 if ( ! defined( 'GHOSTKIT_VERSION' ) ) {
56 define( 'GHOSTKIT_VERSION', '3.7.1' );
57 }
58
59 if ( ! class_exists( 'GhostKit' ) ) :
60 /**
61 * GhostKit Class
62 */
63 class GhostKit {
64
65 /**
66 * The single class instance.
67 *
68 * @var $instance
69 */
70 private static $instance = null;
71
72 /**
73 * Path to the plugin directory
74 *
75 * @var $plugin_path
76 */
77 public $plugin_path;
78
79 /**
80 * URL to the plugin directory
81 *
82 * @var $plugin_url
83 */
84 public $plugin_url;
85
86 /**
87 * Plugin name
88 *
89 * @var $plugin_name
90 */
91 public $plugin_name;
92
93 /**
94 * Plugin version
95 *
96 * @var $plugin_version
97 */
98 public $plugin_version;
99
100 /**
101 * Plugin slug
102 *
103 * @var $plugin_slug
104 */
105 public $plugin_slug;
106
107 /**
108 * Plugin name sanitized
109 *
110 * @var $plugin_name_sanitized
111 */
112 public $plugin_name_sanitized;
113
114 /**
115 * GhostKit constructor.
116 */
117 public function __construct() {
118 /* We do nothing here! */
119 }
120
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 }
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__ );
140
141 require_once $this->plugin_path . 'settings/index.php';
142 require_once $this->plugin_path . 'gutenberg/index.php';
143
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-scss-replace-modules.php';
155 require_once $this->plugin_path . 'classes/class-scss-compiler.php';
156 require_once $this->plugin_path . 'classes/class-breakpoints-background.php';
157 require_once $this->plugin_path . 'classes/class-breakpoints.php';
158 require_once $this->plugin_path . 'classes/class-ask-review.php';
159 require_once $this->plugin_path . 'classes/class-deactivate-duplicate-plugin.php';
160
161 require_once $this->plugin_path . 'gutenberg/utils/encode-decode/index.php';
162 require_once $this->plugin_path . 'gutenberg/extend/index.php';
163
164 // 3rd.
165 require_once $this->plugin_path . 'classes/3rd/class-astra.php';
166 require_once $this->plugin_path . 'classes/3rd/class-page-builder-framework.php';
167 require_once $this->plugin_path . 'classes/3rd/class-blocksy.php';
168 require_once $this->plugin_path . 'classes/3rd/class-rank-math.php';
169
170 // Migration.
171 require_once $this->plugin_path . 'classes/class-migration.php';
172 }
173
174 /**
175 * Init hooks
176 */
177 public function init_hooks() {
178 add_action( 'admin_init', array( $this, 'admin_init' ) );
179
180 add_action( 'init', array( $this, 'init_hook' ) );
181
182 add_action( 'init', array( $this, 'add_custom_fields_support' ), 100 );
183
184 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'add_go_pro_link_plugins_page' ) );
185
186 add_action( 'wp_enqueue_scripts', array( $this, 'js_translation' ), 11 );
187 add_action( 'enqueue_block_editor_assets', array( $this, 'js_translation_editor' ) );
188
189 // add Ghost Kit blocks category.
190 add_filter( 'block_categories_all', array( $this, 'block_categories_all' ), 9999 );
191
192 // we need to enqueue the main script earlier to let 3rd-party plugins add custom styles support.
193 add_action( 'enqueue_block_assets', array( $this, 'enqueue_block_assets' ), 9 );
194
195 // add support for excerpts to some blocks.
196 add_filter( 'excerpt_allowed_blocks', array( $this, 'excerpt_allowed_blocks' ) );
197
198 // add support for additional mimes.
199 add_filter( 'upload_mimes', array( $this, 'upload_mimes' ), 100 );
200 add_filter( 'wp_check_filetype_and_ext', array( $this, 'wp_check_filetype_and_ext' ), 100, 3 );
201 }
202
203 /**
204 * JS translation.
205 */
206 public function js_translation() {
207 if ( ! function_exists( 'wp_set_script_translations' ) ) {
208 return;
209 }
210
211 wp_set_script_translations( 'ghostkit-block-countdown', 'ghostkit', plugin_dir_path( __FILE__ ) . '/languages' );
212 }
213
214 /**
215 * JS translation for editor.
216 */
217 public function js_translation_editor() {
218 if ( ! function_exists( 'wp_set_script_translations' ) ) {
219 return;
220 }
221
222 wp_set_script_translations( 'ghostkit-editor', 'ghostkit', plugin_dir_path( __FILE__ ) . '/languages' );
223 wp_set_script_translations( 'ghostkit-settings', 'ghostkit', plugin_dir_path( __FILE__ ) . '/languages' );
224 }
225
226 /**
227 * Register Ghost Kit blocks category
228 *
229 * @param array $categories - available categories.
230 * @return array
231 */
232 public function block_categories_all( $categories ) {
233 return array_merge(
234 array(
235 array(
236 'slug' => 'ghostkit',
237 'title' => __( 'Ghost Kit', 'ghostkit' ),
238 ),
239 ),
240 $categories
241 );
242 }
243
244 /**
245 * Enqueue editor assets
246 */
247 public function enqueue_block_assets() {
248 if ( ! is_admin() ) {
249 return;
250 }
251
252 global $current_screen;
253
254 $css_deps = array();
255 $js_deps = array( 'ghostkit-helper' );
256
257 // Ivent.
258 if ( apply_filters( 'gkt_enqueue_plugin_ivent', true ) ) {
259 $js_deps[] = 'ivent';
260 }
261
262 // Motion.
263 if ( apply_filters( 'gkt_enqueue_plugin_motion', true ) ) {
264 $js_deps[] = 'motion';
265 }
266
267 // Jarallax.
268 if ( apply_filters( 'gkt_enqueue_plugin_jarallax', true ) ) {
269 $js_deps[] = 'jarallax';
270 $js_deps[] = 'jarallax-video';
271 }
272
273 // Luxon.
274 if ( apply_filters( 'gkt_enqueue_plugin_luxon', true ) ) {
275 $js_deps[] = 'luxon';
276 }
277
278 // Lottie Player.
279 if ( apply_filters( 'gkt_enqueue_plugin_lottie_player', true ) ) {
280 $js_deps[] = 'lottie-player';
281 }
282
283 // GistEmbed.
284 if ( apply_filters( 'gkt_enqueue_plugin_gist_simple', true ) ) {
285 $css_deps[] = 'gist-simple';
286 $js_deps[] = 'gist-simple';
287 }
288
289 // In block metadata, many Ghost Kit blocks declare `style: ["ghostkit", ...]`.
290 // Because of this, WordPress auto-enqueues the `ghostkit` style handle for those blocks
291 // in every context where blocks are rendered, including the editor.
292 //
293 // `ghostkit` is our frontend stylesheet (`build/gutenberg/style.css`), while editor UI
294 // is styled by `ghostkit-editor` (`build/gutenberg/editor.css`). Loading both in editor
295 // causes conflicts (for example, frontend Display extension rules can hide editor blocks).
296 //
297 // To keep block dependency chains intact without editing all block.json files, we override
298 // only the `ghostkit` handle in admin and make it an alias that depends on `ghostkit-editor`.
299 // Result:
300 // - frontend keeps using real `ghostkit` styles;
301 // - editor resolves `ghostkit` dependencies to editor styles, avoiding CSS conflicts.
302 if ( wp_style_is( 'ghostkit', 'registered' ) ) {
303 wp_deregister_style( 'ghostkit' );
304 }
305 wp_register_style( 'ghostkit', false, array( 'ghostkit-editor' ), GHOSTKIT_VERSION );
306
307 // Ghost Kit.
308 GhostKit_Assets::enqueue_style(
309 'ghostkit-editor',
310 'build/gutenberg/editor',
311 $css_deps,
312 filemtime( plugin_dir_path( __FILE__ ) . 'build/gutenberg/editor.css' )
313 );
314 wp_style_add_data( 'ghostkit-editor', 'rtl', 'replace' );
315 wp_style_add_data( 'ghostkit-editor', 'suffix', '.min' );
316
317 // Since WordPress 7.1 the post editor canvas is always iframed, and core collects
318 // the iframe assets by running `enqueue_block_assets` a second time with
319 // `should_load_block_editor_scripts_and_styles` forced to false.
320 // The editor bundles belong to the editor chrome only - loading them in the canvas
321 // would boot a second copy of the block editor inside the iframe. The vendor
322 // libraries, on the other hand, are needed inside the canvas to render block previews
323 // (for example the `lottie-player` custom element, which is registered per window).
324 if ( ! wp_should_load_block_editor_scripts_and_styles() ) {
325 foreach ( $js_deps as $dep ) {
326 wp_enqueue_script( $dep );
327 }
328
329 return;
330 }
331
332 GhostKit_Assets::enqueue_script(
333 'ghostkit-editor',
334 'build/gutenberg/index',
335 $js_deps
336 );
337
338 // Load plugins in editor only (skip legacy Widgets screen).
339 if ( ! isset( $current_screen->id ) || 'widgets' !== $current_screen->id ) {
340 GhostKit_Assets::enqueue_script(
341 'ghostkit-editor-plugins',
342 'build/gutenberg/plugins',
343 array( 'ghostkit-editor' )
344 );
345 }
346 }
347
348 /**
349 * Excerpt allowed wrapper blocks.
350 *
351 * @param array $blocks - allowed blocks.
352 * @return array
353 */
354 public function excerpt_allowed_blocks( $blocks ) {
355 return array_merge(
356 $blocks,
357 array(
358 'ghostkit/accordion',
359 'ghostkit/accordion-item',
360 'ghostkit/alert',
361 'ghostkit/button',
362 'ghostkit/carousel',
363 'ghostkit/carousel-single',
364 'ghostkit/changelog',
365 'ghostkit/counter-box',
366 'ghostkit/grid',
367 'ghostkit/grid-column',
368 'ghostkit/icon-box',
369 'ghostkit/pricing-table',
370 'ghostkit/pricing-table-item',
371 'ghostkit/tabs-v2',
372 'ghostkit/tabs-tab-v2',
373 'ghostkit/testimonial',
374 )
375 );
376 }
377
378 /**
379 * Allow JSON uploads
380 *
381 * @param array $mimes supported mimes.
382 *
383 * @return array
384 */
385 public function upload_mimes( $mimes ) {
386 if ( ! isset( $mimes['json'] ) ) {
387 $mimes['json'] = 'application/json';
388 }
389
390 return $mimes;
391 }
392
393 /**
394 * Allow JSON file uploads
395 *
396 * @param array $data File data.
397 * @param array $file File object.
398 * @param string $filename File name.
399 *
400 * @return array
401 */
402 public function wp_check_filetype_and_ext( $data, $file, $filename ) {
403 $ext = isset( $data['ext'] ) ? $data['ext'] : '';
404
405 if ( ! $ext ) {
406 $exploded = explode( '.', $filename );
407 $ext = strtolower( end( $exploded ) );
408 }
409
410 if ( 'json' === $ext ) {
411 $data['type'] = 'application/json';
412 $data['ext'] = 'json';
413 }
414
415 return $data;
416 }
417
418 /**
419 * Init variables
420 */
421 public function admin_init() {
422 // get current plugin data.
423 $data = get_plugin_data( __FILE__ );
424 $this->plugin_name = $data['Name'];
425 $this->plugin_version = $data['Version'];
426 $this->plugin_slug = plugin_basename( __FILE__ );
427 $this->plugin_name_sanitized = basename( __FILE__, '.php' );
428 }
429
430 /**
431 * Init hook
432 */
433 public function init_hook() {
434 load_plugin_textdomain( 'ghostkit', false, plugin_dir_path( __FILE__ ) . '/languages' );
435 }
436
437 /**
438 * Add support for 'custom-fields' for all post types.
439 * Required by Customizer and Custom CSS blocks.
440 */
441 public function add_custom_fields_support() {
442 $available_post_types = get_post_types(
443 array(
444 'show_ui' => true,
445 ),
446 'object'
447 );
448
449 foreach ( $available_post_types as $post_type ) {
450 if ( 'attachment' !== $post_type->name ) {
451 add_post_type_support( $post_type->name, 'custom-fields' );
452 }
453 }
454 }
455
456 /**
457 * Equivalent of GHOSTKIT.replaceVars method.
458 *
459 * @param string $str styles string.
460 * @return string string with replaced vars.
461 */
462 public function replace_vars( $str ) {
463 $breakpoints = GhostKit_Breakpoints::get_breakpoints();
464 // TODO: Due to different formats in scss and assets there is an offset.
465 $vars = array(
466 'media_sm' => '(max-width: ' . $breakpoints['xs'] . 'px)',
467 'media_md' => '(max-width: ' . $breakpoints['sm'] . 'px)',
468 'media_lg' => '(max-width: ' . $breakpoints['md'] . 'px)',
469 'media_xl' => '(max-width: ' . $breakpoints['lg'] . 'px)',
470 );
471
472 foreach ( $vars as $k => $var ) {
473 $str = preg_replace( "/#{ghostkitvar:$k}/", $var, $str );
474 }
475
476 return $str;
477 }
478
479 /**
480 * Add Go Pro link to plugins page.
481 *
482 * @param array $links - available links.
483 *
484 * @return array
485 */
486 public function add_go_pro_link_plugins_page( $links ) {
487 return array_merge(
488 $links,
489 array(
490 '<a target="_blank" href="admin.php?page=ghostkit_go_pro&utm_medium=plugins_list">' . esc_html__( 'Go Pro', 'ghostkit' ) . '</a>',
491 )
492 );
493 }
494
495 /**
496 * Get Go Pro link
497 *
498 * @return string
499 */
500 public function go_pro_link() {
501 return 'https://www.ghostkit.io/pricing/';
502 }
503 }
504
505 /**
506 * Function works with the GhostKit class instance
507 *
508 * @return object GhostKit
509 */
510 function ghostkit() {
511 return GhostKit::instance();
512 }
513 add_action( 'plugins_loaded', 'ghostkit' );
514 endif;
515