PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / trunk
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages vtrunk
3.4.1 3.4.0 3.3.9 3.3.8 3.3.7 3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 2.3.0 2.3.1 2.3.2 2.3.3 All 194 releases
convertkit / includes / class-wp-convertkit.php

class-wp-convertkit.php in Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages trunk, at includes/class-wp-convertkit.php

492 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 * ConvertKit class.
4 *
5 * @package ConvertKit
6 * @author ConvertKit
7 */
8
9 /**
10 * Class ConvertKit
11 *
12 * @package ConvertKit
13 * @author ConvertKit
14 */
15 class WP_ConvertKit {
16
17 /**
18 * Holds the class object.
19 *
20 * @since 1.9.6
21 *
22 * @var object
23 */
24 private static $instance;
25
26 /**
27 * Holds singleton initialized classes that include
28 * action and filter hooks.
29 *
30 * @since 1.9.6
31 *
32 * @var array
33 */
34 private $classes = array();
35
36 /**
37 * Constructor. Acts as a bootstrap to load the rest of the plugin
38 *
39 * @since 1.9.6
40 */
41 public function __construct() {
42
43 // Initialize classes that have hooks prior to the `init` hook.
44 // Divi Theme requires us to do this, although the Divi Builder Plugin works fine when loading
45 // our integration on `init`.
46 $this->classes['divi'] = new ConvertKit_Divi();
47 $this->classes['widgets'] = new ConvertKit_Widgets();
48
49 // Initialize Plugin classes on init, so the `_load_textdomain_just_in_time` warning isn't triggered.
50 add_action( 'init', array( $this, 'initialize' ), 1 );
51 add_action( 'init', array( $this, 'setup' ), 2 );
52
53 }
54
55 /**
56 * Initialize classes.
57 *
58 * @since 2.7.7
59 */
60 public function initialize() {
61
62 $this->initialize_admin();
63 $this->initialize_admin_or_frontend_editor();
64 $this->initialize_cli_cron();
65 $this->initialize_frontend();
66 $this->initialize_global();
67 $this->initialize_mcp();
68
69 }
70
71 /**
72 * Initialize classes for the WordPress Administration interface
73 *
74 * @since 1.9.6
75 */
76 private function initialize_admin() {
77
78 // Bail if this request isn't for the WordPress Administration interface.
79 if ( ! is_admin() ) {
80 return;
81 }
82
83 $this->classes['admin_bulk_edit'] = new ConvertKit_Admin_Bulk_Edit();
84 $this->classes['admin_cache_plugins'] = new ConvertKit_Admin_Cache_Plugins();
85 $this->classes['admin_category'] = new ConvertKit_Admin_Category();
86 $this->classes['admin_landing_page'] = new ConvertKit_Admin_Landing_Page();
87 $this->classes['admin_legacy_resource_notice'] = new ConvertKit_Admin_Legacy_Resource_Notice();
88 $this->classes['admin_importer_activecampaign'] = new ConvertKit_Admin_Importer_ActiveCampaign();
89 $this->classes['admin_importer_aweber'] = new ConvertKit_Admin_Importer_AWeber();
90 $this->classes['admin_importer_campaignmonitor'] = new ConvertKit_Admin_Importer_CampaignMonitor();
91 $this->classes['admin_importer_convertkit_legacy_forms'] = new ConvertKit_Admin_Importer_ConvertKit_Legacy_Forms();
92 $this->classes['admin_importer_mc4wp'] = new ConvertKit_Admin_Importer_MC4WP();
93 $this->classes['admin_importer_mailpoet'] = new ConvertKit_Admin_Importer_Mailpoet();
94 $this->classes['admin_importer_newsletter'] = new ConvertKit_Admin_Importer_Newsletter();
95 $this->classes['admin_post'] = new ConvertKit_Admin_Post();
96 $this->classes['admin_quick_edit'] = new ConvertKit_Admin_Quick_Edit();
97 $this->classes['admin_restrict_content'] = new ConvertKit_Admin_Restrict_Content();
98 $this->classes['admin_settings'] = new ConvertKit_Admin_Settings();
99 $this->classes['admin_setup_wizard_landing_page'] = new ConvertKit_Admin_Setup_Wizard_Landing_Page();
100 $this->classes['admin_setup_wizard_plugin'] = new ConvertKit_Admin_Setup_Wizard_Plugin();
101 $this->classes['admin_setup_wizard_restrict_content'] = new ConvertKit_Admin_Setup_Wizard_Restrict_Content();
102
103 /**
104 * Initialize integration classes for the WordPress Administration interface.
105 *
106 * @since 1.9.6
107 */
108 do_action( 'convertkit_initialize_admin' );
109
110 }
111
112 /**
113 * Initialize classes for the WordPress Administration interface or a frontend Page Builder
114 *
115 * @since 1.9.6
116 */
117 private function initialize_admin_or_frontend_editor() {
118
119 // Bail if this request isn't for the WordPress Administration interface and isn't for a frontend Page Builder.
120 if ( ! $this->is_admin_or_frontend_editor() ) {
121 return;
122 }
123
124 /**
125 * Initialize integration classes for the WordPress Administration interface or a frontend Page Builder.
126 *
127 * @since 1.9.6
128 */
129 do_action( 'convertkit_initialize_admin_or_frontend_editor' );
130
131 }
132
133 /**
134 * Initialize classes for WP-CLI and WP-Cron
135 *
136 * @since 2.5.2
137 */
138 private function initialize_cli_cron() {
139
140 // Bail if this isn't a CLI or CRON request.
141 if ( ! $this->is_cli() && ! $this->is_cron() ) {
142 return;
143 }
144
145 /**
146 * Initialize integration classes for WP-CLI and WP-Cron.
147 *
148 * @since 1.9.6
149 */
150 do_action( 'convertkit_initialize_cli_cron' );
151
152 }
153
154 /**
155 * Initialize classes for the frontend web site
156 *
157 * @since 1.9.6
158 */
159 private function initialize_frontend() {
160
161 // Bail if this request isn't for the frontend web site.
162 if ( is_admin() ) {
163 return;
164 }
165
166 $this->classes['cache_plugins'] = new ConvertKit_Cache_Plugins();
167 $this->classes['output'] = new ConvertKit_Output();
168 $this->classes['output_broadcasts'] = new ConvertKit_Output_Broadcasts();
169
170 /**
171 * Initialize integration classes for the frontend web site.
172 *
173 * @since 1.9.6
174 */
175 do_action( 'convertkit_initialize_frontend' );
176
177 }
178
179 /**
180 * Initialize classes required globally, across the WordPress Administration, CLI, Cron and Frontend
181 * web site.
182 *
183 * @since 1.9.6
184 */
185 private function initialize_global() {
186
187 $this->classes['admin_notices'] = new ConvertKit_Admin_Notices();
188 $this->classes['admin_tinymce'] = new ConvertKit_Admin_TinyMCE();
189 $this->classes['admin_refresh_resources'] = new ConvertKit_Admin_Refresh_Resources();
190 $this->classes['blocks_convertkit_broadcasts'] = new ConvertKit_Block_Broadcasts();
191 $this->classes['blocks_convertkit_content'] = new ConvertKit_Block_Content();
192 $this->classes['blocks_convertkit_formtrigger'] = new ConvertKit_Block_Form_Trigger();
193 $this->classes['blocks_convertkit_form'] = new ConvertKit_Block_Form();
194 $this->classes['blocks_convertkit_form_builder'] = new ConvertKit_Block_Form_Builder();
195 $this->classes['blocks_convertkit_form_builder_field_email'] = new ConvertKit_Block_Form_Builder_Field_Email();
196 $this->classes['blocks_convertkit_form_builder_field_name'] = new ConvertKit_Block_Form_Builder_Field_Name();
197 $this->classes['blocks_convertkit_form_builder_field_custom'] = new ConvertKit_Block_Form_Builder_Field_Custom();
198 $this->classes['blocks_convertkit_product'] = new ConvertKit_Block_Product();
199 $this->classes['block_formatter_form_link'] = new ConvertKit_Block_Formatter_Form_Link();
200 $this->classes['block_formatter_product_link'] = new ConvertKit_Block_Formatter_Product_Link();
201 $this->classes['pre_publish_action_broadcast_export'] = new ConvertKit_Pre_Publish_Action_Broadcast_Export();
202 $this->classes['plugin_sidebar_post_settings'] = new ConvertKit_Plugin_Sidebar_Post_Settings();
203 $this->classes['broadcasts_exporter'] = new ConvertKit_Broadcasts_Exporter();
204 $this->classes['broadcasts_importer'] = new ConvertKit_Broadcasts_Importer();
205 $this->classes['elementor'] = new ConvertKit_Elementor();
206 $this->classes['gutenberg'] = new ConvertKit_Gutenberg();
207 $this->classes['mcp'] = new ConvertKit_MCP();
208 $this->classes['media_library'] = new ConvertKit_Media_Library();
209 $this->classes['output_restrict_content'] = new ConvertKit_Output_Restrict_Content();
210 $this->classes['restrict_content_cache'] = new ConvertKit_Restrict_Content_Cache();
211 $this->classes['review_request'] = new ConvertKit_Review_Request( 'Kit', 'convertkit', CONVERTKIT_PLUGIN_PATH );
212 $this->classes['preview_output'] = new ConvertKit_Preview_Output();
213 $this->classes['setup'] = new ConvertKit_Setup();
214 $this->classes['shortcodes'] = new ConvertKit_Shortcodes();
215
216 /**
217 * Initialize integration classes for the frontend web site.
218 *
219 * @since 1.9.6
220 */
221 do_action( 'convertkit_initialize_global' );
222
223 }
224
225 /**
226 * Initializes the MCP server if enabled in the Plugin's settings.
227 *
228 * @since 3.4.0
229 */
230 public function initialize_mcp() {
231
232 // Bail if the MCP server is not enabled.
233 $settings = new ConvertKit_Settings_MCP();
234 if ( ! $settings->enabled() ) {
235 return;
236 }
237
238 // Bail if the Abilities API is unavailable (WordPress < 6.9).
239 if ( ! function_exists( 'wp_register_ability' ) ) {
240 return;
241 }
242
243 // Bail if PHP 7.4+ is not installed, as this is required for the MCP Adapter classes.
244 if ( version_compare( PHP_VERSION, '7.4', '<' ) ) {
245 return;
246 }
247
248 // Load MCP Adapter if another Plugin hasn't already loaded it.
249 if ( ! class_exists( 'WP\\MCP\\Core\\McpAdapter' ) ) {
250 // Bail if the WordPress MCP Adapter autoloader is missing.
251 if ( ! file_exists( CONVERTKIT_PLUGIN_PATH . '/vendor/autoload.php' ) ) {
252 return;
253 }
254
255 // Load MCP Adapter.
256 require_once CONVERTKIT_PLUGIN_PATH . '/vendor/autoload.php';
257
258 // Bail if the MCP Adapter class doesn't exist - something went wrong with the autoloader.
259 if ( ! class_exists( 'WP\\MCP\\Core\\McpAdapter' ) ) { // @phpstan-ignore-line
260 return;
261 }
262 }
263
264 // Bootstrap the MCP Adapter, per WordPress/mcp-adapter's recommended
265 // integration pattern.
266 // @see https://github.com/WordPress/mcp-adapter#using-mcp-adapter-in-your-plugin.
267 \WP\MCP\Core\McpAdapter::instance();
268
269 }
270
271 /**
272 * Runs the Plugin's initialization and update routines, which checks if
273 * the Plugin has just been updated to a newer version,
274 * and if so runs any specific processes that might be needed.
275 *
276 * @since 1.9.7.4
277 */
278 public function setup() {
279
280 $this->get_class( 'setup' )->initialize();
281 $this->get_class( 'setup' )->update();
282
283 }
284
285 /**
286 * Improved version of WordPress' is_admin(), which includes whether we're
287 * editing on the frontend using a Page Builder.
288 *
289 * @since 1.9.6
290 *
291 * @return bool Is Admin or Frontend Editor Request
292 */
293 public function is_admin_or_frontend_editor() {
294
295 // If we're in the wp-admin, return true.
296 if ( is_admin() ) {
297 return true;
298 }
299
300 // Pro.
301 if ( array_key_exists( 'REQUEST_URI', $_SERVER ) ) {
302 if ( strpos( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), '/pro/' ) !== false ) {
303 return true;
304 }
305 if ( strpos( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), '/x/' ) !== false ) {
306 return true;
307 }
308 if ( strpos( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), 'cornerstone-endpoint' ) !== false ) {
309 return true;
310 }
311 }
312
313 // If the request global exists, check for specific request keys which tell us
314 // that we're using a frontend editor.
315 // Avada Live.
316 // phpcs:disable WordPress.Security.NonceVerification.Recommended
317 if ( array_key_exists( 'fb-edit', $_REQUEST ) ) {
318 return true;
319 }
320
321 // Beaver Builder.
322 if ( array_key_exists( 'fl_builder', $_REQUEST ) ) {
323 return true;
324 }
325
326 // Brizy.
327 if ( array_key_exists( 'brizy-edit', $_REQUEST ) ) {
328 return true;
329 }
330
331 // Cornerstone (AJAX).
332 if ( array_key_exists( '_cs_nonce', $_REQUEST ) ) {
333 return true;
334 }
335
336 // Divi.
337 if ( array_key_exists( 'et_fb', $_REQUEST ) ) {
338 return true;
339 }
340
341 // Elementor.
342 if ( array_key_exists( 'action', $_REQUEST ) && sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ) === 'elementor' ) {
343 return true;
344 }
345
346 // Kallyas.
347 if ( array_key_exists( 'zn_pb_edit', $_REQUEST ) ) {
348 return true;
349 }
350
351 // Oxygen.
352 if ( array_key_exists( 'ct_builder', $_REQUEST ) ) {
353 return true;
354 }
355
356 // Thrive Architect.
357 if ( array_key_exists( 'tve', $_REQUEST ) ) {
358 return true;
359 }
360
361 // Visual Composer.
362 if ( array_key_exists( 'vcv-editable', $_REQUEST ) ) {
363 return true;
364 }
365
366 // WPBakery Page Builder.
367 if ( array_key_exists( 'vc_editable', $_REQUEST ) ) {
368 return true;
369 }
370
371 // Zion Builder.
372 if ( array_key_exists( 'action', $_REQUEST ) && sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ) === 'zion_builder_active' ) {
373 return true;
374 }
375
376 // Assume we're not in the Administration interface.
377 $is_admin_or_frontend_editor = false;
378
379 /**
380 * Filters whether the current request is a WordPress Administration / Frontend Editor request or not.
381 *
382 * Page Builders can set this to true to allow ConvertKit to load its administration functionality.
383 *
384 * @since 1.9.6
385 *
386 * @param bool $is_admin_or_frontend_editor Is WordPress Administration / Frontend Editor request.
387 */
388 $is_admin_or_frontend_editor = apply_filters( 'convertkit_is_admin_or_frontend_editor', $is_admin_or_frontend_editor );
389
390 // phpcs:enable
391
392 // Return filtered result.
393 return $is_admin_or_frontend_editor;
394
395 }
396
397 /**
398 * Detects if the request is through the WP-CLI
399 *
400 * @since 1.9.6
401 *
402 * @return bool Is WP-CLI Request
403 */
404 public function is_cli() {
405
406 if ( ! defined( 'WP_CLI' ) ) {
407 return false;
408 }
409 if ( ! WP_CLI ) {
410 return false;
411 }
412
413 return true;
414
415 }
416
417 /**
418 * Detects if the request is through the WP CRON
419 *
420 * @since 1.9.6
421 *
422 * @return bool Is WP CRON Request
423 */
424 public function is_cron() {
425
426 return wp_doing_cron();
427
428 }
429
430 /**
431 * Returns the given class
432 *
433 * @since 1.9.6
434 *
435 * @param string $name Class Name.
436 * @return object Class Object
437 */
438 public function get_class( $name ) {
439
440 // If the class hasn't been loaded, throw a WordPress die screen
441 // to avoid a PHP fatal error.
442 if ( ! isset( $this->classes[ $name ] ) ) {
443 // Define the error.
444 $error = new WP_Error(
445 'convertkit_get_class',
446 sprintf(
447 /* translators: %1$s: PHP class name */
448 __( 'Kit Error: Could not load Plugin class <strong>%1$s</strong>', 'convertkit' ),
449 $name
450 )
451 );
452
453 // Depending on the request, return or display an error.
454 // Admin UI.
455 if ( is_admin() ) {
456 wp_die(
457 esc_attr( $error->get_error_message() ),
458 esc_html__( 'Kit Error', 'convertkit' ),
459 array(
460 'back_link' => true,
461 )
462 );
463 }
464
465 // Cron / CLI.
466 return $error;
467 }
468
469 // Return the class object.
470 return $this->classes[ $name ];
471
472 }
473
474 /**
475 * Returns the singleton instance of the class.
476 *
477 * @since 1.1.6
478 *
479 * @return object Class.
480 */
481 public static function get_instance() {
482
483 if ( null === self::$instance ) {
484 self::$instance = new self();
485 }
486
487 return self::$instance;
488
489 }
490
491 }
492