PluginProbe
SureContact – Newsletters, Email Marketing, Automation, Revenue Tracking & CRM / 1.3.1
SureContact – Newsletters, Email Marketing, Automation, Revenue Tracking & CRM v1.3.1
1.5.4 1.5.3 1.5.2 1.5.1 trunk 0.0.2 0.0.3 0.0.4 0.0.5 1.0.0 1.1.0 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.5.0
surecontact / surecontact.php

surecontact.php in SureContact – Newsletters, Email Marketing, Automation, Revenue Tracking & CRM 1.3.1, at surecontact.php

484 lines 11.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: SureContact – Newsletters, Email Marketing, Automation, Revenue Tracking & CRM
4 * Plugin URI: https://surecontact.com
5 * Description: Send newsletters, set up email automations, manage contacts and track ecommerce revenue in a CRM for WordPress.
6 * Version: 1.3.1
7 * Author: SureContact
8 * Author URI: https://profiles.wordpress.org/brainstormforce/
9 * License: GPLv2 or later
10 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
11 * Text Domain: surecontact
12 * Domain Path: /languages
13 * Requires at least: 5.8
14 * Tested up to: 6.9
15 * Requires PHP: 7.4
16 *
17 * @since 0.0.1
18 *
19 * @package SureContact
20 */
21
22 // Exit if accessed directly.
23 if ( ! defined( 'ABSPATH' ) ) {
24 exit;
25 }
26
27 /**
28 * SaaS API Base URL constant
29 *
30 * @since 0.0.1
31 */
32 if ( ! defined( 'SURECONTACT_SAAS_API_BASE_URL' ) ) {
33 define( 'SURECONTACT_SAAS_API_BASE_URL', 'https://api.surecontact.com' );
34 }
35
36 /**
37 * SaaS SDK Base URL constant
38 *
39 * @since 0.0.1
40 */
41 if ( ! defined( 'SURECONTACT_SAAS_BASE_URL' ) ) {
42 define( 'SURECONTACT_SAAS_BASE_URL', 'https://app.surecontact.com' );
43 }
44
45 /**
46 * Main plugin class
47 *
48 * Singleton pattern implementation for SureContact plugin.
49 * Handles plugin initialization, dependency loading, and lifecycle hooks.
50 *
51 * @since 0.0.1
52 */
53 final class SureContact {
54
55 /**
56 * Plugin version
57 *
58 * @since 0.0.1
59 *
60 * @var string
61 */
62 const VERSION = '1.3.1';
63
64 /**
65 * Plugin singleton instance
66 *
67 * @since 0.0.1
68 *
69 * @var SureContact|null
70 */
71 private static $instance = null;
72
73 /**
74 * Plugin directory path
75 *
76 * @since 0.0.1
77 *
78 * @var string
79 */
80 private $plugin_path;
81
82 /**
83 * Plugin directory URL
84 *
85 * @since 0.0.1
86 *
87 * @var string
88 */
89 private $plugin_url;
90
91 /**
92 * Integrations loader instance
93 *
94 * @since 0.0.1
95 *
96 * @var SureContact\Integrations_Loader|null
97 */
98 public $integrations_loader;
99
100 /**
101 * Daily Sync Manager instance
102 *
103 * @since 0.0.1
104 *
105 * @var SureContact\Daily_Sync_Manager|null
106 */
107 private $daily_sync_manager;
108
109
110 /**
111 * Bulk Sync Service instance
112 *
113 * @since 0.0.1
114 *
115 * @var SureContact\Bulk_Sync_Service|null
116 */
117 private $bulk_sync_service;
118
119 /**
120 * Admin Menu instance
121 *
122 * @since 0.0.1
123 *
124 * @var SureContact\Admin\Admin_Menu|null
125 */
126 private $admin_menu;
127
128
129 /**
130 * Queue Manager instance
131 *
132 * @since 0.0.1
133 *
134 * @var SureContact\Queue_Manager|null
135 */
136 private $queue_manager;
137
138 /**
139 * Get singleton instance
140 *
141 * Implements lazy loading for better performance.
142 *
143 * @since 0.0.1
144 *
145 * @return SureContact
146 */
147 public static function get_instance() {
148 if ( is_null( self::$instance ) ) {
149 self::$instance = new self();
150 }
151 return self::$instance;
152 }
153
154 /**
155 * Private constructor to prevent direct instantiation
156 *
157 * @since 0.0.1
158 */
159 private function __construct() {
160 $this->define_constants();
161 $this->setup_hooks();
162 $this->load_dependencies();
163 $this->init_hooks();
164 }
165
166 /**
167 * Define plugin constants
168 *
169 * @since 0.0.1
170 *
171 * @return void
172 */
173 private function define_constants() {
174 $this->plugin_path = plugin_dir_path( __FILE__ );
175 $this->plugin_url = plugin_dir_url( __FILE__ );
176
177 define( 'SURECONTACT_VERSION', self::VERSION );
178 define( 'SURECONTACT_PLUGIN_PATH', $this->plugin_path );
179 define( 'SURECONTACT_PLUGIN_URL', $this->plugin_url );
180 define( 'SURECONTACT_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
181 }
182
183 /**
184 * Setup activation and deactivation hooks
185 *
186 * @since 0.0.1
187 *
188 * @return void
189 */
190 private function setup_hooks() {
191 register_activation_hook( __FILE__, array( $this, 'activate' ) );
192 register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) );
193 }
194
195 /**
196 * Load required dependencies
197 *
198 * @since 0.0.1
199 *
200 * @return void
201 */
202 private function load_dependencies() {
203 $this->load_action_scheduler();
204
205 // Load global helper functions.
206 require_once SURECONTACT_PLUGIN_PATH . 'includes/functions.php';
207
208 $autoloader_path = SURECONTACT_PLUGIN_PATH . 'includes/class-autoloader.php';
209 if ( file_exists( $autoloader_path ) ) {
210 require_once $autoloader_path;
211 } else {
212 // Autoloader not loaded yet, use direct error_log.
213 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
214 error_log(
215 '[' . gmdate( 'Y-m-d H:i:s' ) . '] SureContact [ERROR] Plugin: Critical error - autoloader not found at ' . $autoloader_path
216 );
217 }
218 }
219
220 /**
221 * Initialize plugin components via WordPress hooks
222 *
223 * @since 0.0.1
224 *
225 * @return void
226 */
227 private function init_hooks() {
228 // Ensure database tables exist (safety check for edge cases).
229 add_action( 'plugins_loaded', array( $this, 'maybe_create_tables' ), 1 );
230
231 add_action( 'init', array( $this, 'init_queue_manager' ), 2 );
232 add_action( 'init', array( $this, 'init_daily_sync_manager' ), 3 );
233 add_action( 'init', array( $this, 'init_bulk_sync_service' ), 5 );
234 // Load integrations early on init hook to ensure hooks are registered before plugin actions fire.
235 add_action( 'init', array( $this, 'init_integrations' ), 5 );
236 add_action( 'rest_api_init', array( $this, 'init_rest_api' ) );
237
238 SureContact\Abilities\Abilities_Loader::instance()->init();
239
240 if ( is_admin() ) {
241 add_action( 'admin_menu', array( $this, 'init_admin_menus' ) );
242 add_filter( 'plugin_action_links_' . SURECONTACT_PLUGIN_BASENAME, array( $this, 'add_action_links' ) );
243 add_filter( 'plugin_row_meta', array( $this, 'add_meta_links' ), 10, 2 );
244 }
245 }
246
247 /**
248 * Initialize Queue Manager
249 *
250 * Initializes early to register Action Scheduler hooks for background processing.
251 *
252 * @since 0.0.1
253 *
254 * @return void
255 */
256 public function init_queue_manager() {
257 if ( is_null( $this->queue_manager ) ) {
258 $this->queue_manager = new SureContact\Queue_Manager();
259 }
260 }
261
262
263 /**
264 * Initialize Daily Sync Manager
265 *
266 * @since 0.0.1
267 *
268 * @return void
269 */
270 public function init_daily_sync_manager() {
271 if ( is_null( $this->daily_sync_manager ) ) {
272 $this->daily_sync_manager = new SureContact\Daily_Sync_Manager();
273 }
274 }
275
276
277 /**
278 * Initialize admin menus
279 *
280 * @since 0.0.1
281 *
282 * @return void
283 */
284 public function init_admin_menus() {
285 if ( is_null( $this->admin_menu ) ) {
286 $this->admin_menu = new SureContact\Admin\Admin_Menu();
287 }
288 }
289
290 /**
291 * Initialize REST API
292 *
293 * @since 0.0.1
294 *
295 * @return void
296 */
297 public function init_rest_api() {
298 $rest_controller = new SureContact\API_WP\Rest_Controller();
299 $rest_controller->register_routes();
300
301 SureContact\API_WP\Api_Init::instance();
302 }
303
304 /**
305 * Initialize Bulk Sync Service
306 *
307 * @since 0.0.1
308 *
309 * @return void
310 */
311 public function init_bulk_sync_service() {
312 if ( is_null( $this->bulk_sync_service ) ) {
313 $this->bulk_sync_service = new SureContact\Bulk_Sync_Service();
314 }
315 }
316
317 /**
318 * Initialize integrations loader
319 *
320 * @since 0.0.1
321 *
322 * @return void
323 */
324 public function init_integrations() {
325 $this->integrations_loader = new SureContact\Integrations_Loader();
326 }
327
328 /**
329 * Plugin activation handler
330 *
331 * Creates database tables and performs initial setup.
332 *
333 * @since 0.0.1
334 *
335 * @return void
336 */
337 public function activate() {
338 // Create database tables.
339 require_once SURECONTACT_PLUGIN_PATH . 'includes/database/class-api-queue-table.php';
340 require_once SURECONTACT_PLUGIN_PATH . 'includes/database/class-integrations-table.php';
341
342 SureContact\Database\API_Queue_Table::create_table();
343 SureContact\Database\Integrations_Table::create_table();
344
345 flush_rewrite_rules();
346 }
347
348 /**
349 * Maybe create or update tables and run migrations.
350 *
351 * Runs on plugins_loaded to ensure tables exist and are up to date.
352 * Each table class handles its own version checking and update logic.
353 * Handles edge cases where activation hook didn't run (multisite, manual install, etc.).
354 *
355 * @since 0.0.1
356 *
357 * @return void
358 */
359 public function maybe_create_tables() {
360 require_once SURECONTACT_PLUGIN_PATH . 'includes/database/class-api-queue-table.php';
361 require_once SURECONTACT_PLUGIN_PATH . 'includes/database/class-integrations-table.php';
362 require_once SURECONTACT_PLUGIN_PATH . 'includes/class-migration-manager.php';
363
364 SureContact\Database\API_Queue_Table::maybe_create_or_update();
365 SureContact\Database\Integrations_Table::maybe_create_or_update();
366
367 // Run data migrations after tables are ready.
368 SureContact\Migration_Manager::maybe_run_migrations();
369 }
370
371 /**
372 * Plugin deactivation handler
373 *
374 * @since 0.0.1
375 *
376 * @return void
377 */
378 public function deactivate() {
379 flush_rewrite_rules();
380 }
381
382 /**
383 * Add action links to plugin list
384 *
385 * @since 0.0.1
386 *
387 * @param array $links Existing plugin action links.
388 * @return array Modified plugin action links.
389 */
390 public function add_action_links( $links ) {
391 $workspace_uuid = get_option( 'surecontact_workspace_uuid', '' );
392 $is_connected = ! empty( $workspace_uuid );
393
394 $link_text = $is_connected
395 ? __( 'Access Dashboard', 'surecontact' )
396 : __( 'Get Started Now', 'surecontact' );
397
398 $dashboard_link = sprintf(
399 '<a href="%s">%s</a>',
400 esc_url( admin_url( 'admin.php?page=surecontact-dashboard' ) ),
401 esc_html( $link_text )
402 );
403
404 array_unshift( $links, $dashboard_link );
405
406 return $links;
407 }
408
409 /**
410 * Add meta links to the plugin row (under description).
411 *
412 * @since 0.0.3
413 *
414 * @param array<int,string> $links Array of plugin meta links.
415 * @param string $file Plugin file path.
416 * @return array<int,string> Modified plugin meta links.
417 */
418 public function add_meta_links( array $links, string $file ): array {
419 if ( SURECONTACT_PLUGIN_BASENAME === $file ) {
420 $stars = '';
421 for ( $indx = 0; $indx < 5; $indx++ ) {
422 $stars .= '<span class="dashicons dashicons-star-filled" style="color: #ffb900; font-size: 16px; width: 16px; height: 16px; line-height: 1.2;" aria-hidden="true"></span>';
423 }
424 $links[] = sprintf(
425 '<a href="%s" target="_blank" rel="noopener noreferrer" aria-label="%s" role="button">%s</a>',
426 esc_url( 'https://wordpress.org/support/plugin/surecontact/reviews/#new-post' ),
427 esc_attr__( 'Rate our plugin', 'surecontact' ),
428 $stars
429 );
430 }
431 return $links;
432 }
433
434 /**
435 * Get plugin directory path
436 *
437 * @since 0.0.1
438 *
439 * @return string Plugin directory path.
440 */
441 public function get_plugin_path() {
442 return $this->plugin_path;
443 }
444
445 /**
446 * Get plugin directory URL
447 *
448 * @since 0.0.1
449 *
450 * @return string Plugin directory URL.
451 */
452 public function get_plugin_url() {
453 return $this->plugin_url;
454 }
455
456 /**
457 * Load Action Scheduler library
458 *
459 * @since 0.0.1
460 *
461 * @return void
462 */
463 private function load_action_scheduler() {
464 if ( function_exists( 'as_enqueue_async_action' ) ) {
465 return;
466 }
467
468 $action_scheduler_path = SURECONTACT_PLUGIN_PATH . 'lib/action-scheduler/action-scheduler.php';
469
470 if ( file_exists( $action_scheduler_path ) ) {
471 require_once $action_scheduler_path;
472 } else {
473 // Autoloader not loaded yet, use direct error_log.
474 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
475 error_log(
476 '[' . gmdate( 'Y-m-d H:i:s' ) . '] SureContact [ERROR] Plugin: Action Scheduler library not found at ' . $action_scheduler_path
477 );
478 }
479 }
480 }
481
482 // Initialize plugin.
483 $GLOBALS['surecontact'] = SureContact::get_instance();
484