<?php
/*
  Plugin Name: Cool Timeline
  Plugin URI:https://cooltimeline.com
  Description:Showcase your story, company history, events, or roadmap using stunning vertical or horizontal layouts.
  Version:3.3.6
  Author:Cool Plugins
  Author URI:https://coolplugins.net/?utm_source=ctl_plugin&utm_medium=inside&utm_campaign=author_page&utm_content=plugins_list
  License:GPLv2 or later
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
  Domain Path: /languages
  Text Domain:cool-timeline
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}


/** Configuration */
// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
if ( ! defined( 'CTL_V' ) ) {
	define( 'CTL_V', '3.3.6' );
}
// define constants for later use
define( 'CTL_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'CTL_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
if ( ! defined( 'CTL_DEMO_URL' ) ) {
	define( 'CTL_DEMO_URL', 'https://cooltimeline.com/demo/cool-timeline-pro/?utm_source=ctl_plugin&utm_medium=inside&utm_campaign=demo' );
}
define( 'CTL_FEEDBACK_API', 'https://feedback.coolplugins.net/' );
if ( ! defined( 'CTL_BUY_PRO' ) ) {
	define( 'CTL_BUY_PRO', 'https://cooltimeline.com/plugin/cool-timeline-pro/' );
}
// phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound


if ( ! class_exists( 'CoolTimeline' ) ) {
	final class CoolTimeline {


		/**
		 * The unique instance of the plugin.
		 */
		private static $instance;

		/**
		 * Gets an instance of our plugin.
		 */
		public static function get_instance() {
			if ( null === self::$instance ) {
				self::$instance = new self();
			}

			return self::$instance;
		}

		/**
		 * Registers our plugin with WordPress.
		 */
		public static function registers() {
			$thisIns = self::$instance;
			if ( class_exists( 'CoolTimelinePro' ) ) {
				include_once ABSPATH . 'wp-admin/includes/plugin.php';
				deactivate_plugins( 'cool-timeline/cooltimeline.php' );
				return;
			}

			self::register_lifecycle_hooks( $thisIns );
			self::register_core_hooks( $thisIns );

			if ( is_admin() ) {
				self::register_admin_hooks( $thisIns );
			}

			self::register_frontend_hooks( $thisIns );
			self::register_block_integration();
		}

		/**
		 * Register activation/deactivation hooks.
		 *
		 * @param CoolTimeline $plugin Plugin instance.
		 */
		private static function register_lifecycle_hooks( $plugin ) {
			register_activation_hook( __FILE__, array( $plugin, 'ctl_activate' ) );
			register_deactivation_hook( __FILE__, array( $plugin, 'ctl_deactivate' ) );
		}

		/**
		 * Register hooks used by both admin and frontend requests.
		 *
		 * @param CoolTimeline $plugin Plugin instance.
		 */
		private static function register_core_hooks( $plugin ) {
			add_action( 'activated_plugin', array( $plugin, 'ctl_plugin_redirection' ) );
			add_action( 'plugins_loaded', array( $plugin, 'ctl_include_files' ) );
			add_action( 'init', array( $plugin, 'ctl_flush_rules' ) );
			add_action( 'init', array( $plugin, 'ctl_maybe_init_plugin_options' ) );
		}

		/**
		 * Register admin-only hooks and dependencies.
		 *
		 * @param CoolTimeline $plugin Plugin instance.
		 */
		private static function register_admin_hooks( $plugin ) {
			$pluginpath = plugin_basename( __FILE__ );

			add_filter( "plugin_action_links_$pluginpath", array( $plugin, 'ctl_settings_link' ) );
			add_action( 'save_post', array( $plugin, 'ctl_save_story_meta' ), 10, 3 );
			require_once plugin_dir_path( __FILE__ ) . 'admin/marketing/ctl-marketing.php';
			add_action( 'admin_menu', array( $plugin, 'ctl_add_new_item' ) );
			add_action( 'admin_print_scripts', array( $plugin, 'ctl_hide_unrelated_notices' ), 999 );
			add_action( 'admin_enqueue_scripts', array( $plugin, 'ctl_enqueue_addon_fonts' ), 20 );
		}

		/**
		 * Register frontend hooks.
		 *
		 * @param CoolTimeline $plugin Plugin instance.
		 */
		private static function register_frontend_hooks( $plugin ) {
			add_action( 'wp_print_scripts', array( $plugin, 'ctl_deregister_javascript' ), 100 );
		}

		/**
		 * Load Gutenberg block integration.
		 */
		private static function register_block_integration() {
			require CTL_PLUGIN_DIR . 'includes/shortcode-blocks/ctl-block.php';
		}

		

		/** Constructor */
		public function __construct() {
			 // Setup your plugin object here
			 $this->cpfm_load_file();
			 add_action('csf_cool_timeline_settings_save_after', array($this,'ctl_plugin_settings_saved'));
		}
		public function cpfm_load_file(){
			if(!class_exists('CPFM_Feedback_Notice')){
					require_once __DIR__ . '/admin/cpfm-feedback/cpfm-feedback-notice.php';
				}
			require_once __DIR__ . '/includes/cron/class-cron.php';
		}
		public function ctl_add_new_item() {
						add_submenu_page(
				'cool-plugins-timeline-addon',
				__( 'Add New Story', 'cool-timeline' ),
				'<strong>' . esc_html__( 'Add New Story', 'cool-timeline' ) . '</strong>',
				'manage_options',
				'post-new.php?post_type=cool_timeline',
				false,
				15
			);
		}

		public function ctl_plugin_settings_saved(){
			
			if ( $this->ctl_is_tracking_enabled() ) {
				$this->ctl_maybe_schedule_tracking_cron();
			} else {
				if ( wp_next_scheduled( 'ctl_extra_data_update' ) ) {
					wp_clear_scheduled_hook('ctl_extra_data_update');
				}
				
			}
		}

		/**
		 * Check whether usage tracking is enabled in plugin settings.
		 */
		private function ctl_is_tracking_enabled() {
			$data = get_option( 'cool_timeline_settings' );

			return ! empty( $data['ctl_cpfm_feedback_data'] );
		}

		/**
		 * Schedule the usage tracking cron when it is not already scheduled.
		 */
		private function ctl_maybe_schedule_tracking_cron() {
			if ( ! wp_next_scheduled( 'ctl_extra_data_update' ) ) {
				wp_schedule_event( time(), 'every_30_days', 'ctl_extra_data_update' );
			}
		}

		/**
		 * On timeline addon pages, hide unrelated admin notices by pruning the core notice hooks.
		 *
		 * Desired behavior:
		 * - On ALL admin pages: our own plugin notices behave normally.
		 * - Only on Timeline Addons pages: third‑party notices are removed, but our notices remain.
		 *
		 * This follows the same core idea as the Events plugin's ect_hide_unrelated_notices()
		 * but keeps Cool Timeline notices (by class/function name) instead of routing through a
		 * separate dispatcher hook.
		 */
		public function ctl_hide_unrelated_notices() {
			// Always register dispatcher once, on all admin pages (Events-style).
			if ( ! defined( 'CTL_ADMIN_NOTICE_HOOKED' ) ) {
				// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
				define( 'CTL_ADMIN_NOTICE_HOOKED', true );
				add_action(
					'admin_notices',
					array( $this, 'ctl_dash_admin_notices' ),
					PHP_INT_MAX
				);
			}

			// If this is not a Timeline Addons page, don't prune anything.
			if ( ! function_exists( 'ctl_is_timeline_addon_page' ) || ! ctl_is_timeline_addon_page() ) {
				return;
			}

			global $wp_filter;

			$rules = array(
				'user_admin_notices'    => array(), // remove all non‑Cool Plugins callbacks.
				'admin_notices'         => array(),
				'all_admin_notices'     => array(),
				'network_admin_notices' => array(),
				'admin_footer'          => array(
					'render_delayed_admin_notices', // remove this particular callback (e.g. Elementor delayed notices).
				),
			);

			foreach ( array_keys( $rules ) as $notice_type ) {
				if ( empty( $wp_filter[ $notice_type ] ) || empty( $wp_filter[ $notice_type ]->callbacks ) || ! is_array( $wp_filter[ $notice_type ]->callbacks ) ) {
					continue;
				}

				$remove_all = empty( $rules[ $notice_type ] );

				foreach ( $wp_filter[ $notice_type ]->callbacks as $priority => $hooks ) {
					foreach ( $hooks as $name => $arr ) {
						if ( ! isset( $arr['function'] ) ) {
							continue;
						}
						$fn = $arr['function'];

						// When remove_all is true, drop everything EXCEPT Cool Plugins/TWAe callbacks.
						if ( $remove_all ) {
							$keep  = false;
							$class = '';

							if ( is_array( $fn ) && ! empty( $fn[0] ) && is_object( $fn[0] ) ) {
								$class = strtolower( get_class( $fn[0] ) );
							} elseif ( is_object( $fn ) ) {
								$class = strtolower( get_class( $fn ) );
							}

							if ( $class ) {
								$keep = (
									false !== strpos( $class, 'cooltimeline' ) ||
									false !== strpos( $class, 'cool_plugins' ) ||
									false !== strpos( $class, 'ctl_admin' ) ||
									false !== strpos( $class, 'ctp_' ) ||
									false !== strpos( $class, 'license_helper' ) ||
									false !== strpos( $class, 'twae' )
								);
							}

							// Also keep callbacks whose function name clearly belongs to Cool Plugins stack.
							if ( ! $keep && is_string( $fn ) ) {
								$keep = ( 0 === strpos( $fn, 'ctl_' ) || 0 === strpos( $fn, 'cool_' ) || 0 === strpos( $fn, 'twae_' ) );
							}

							if ( ! $keep ) {
								unset( $wp_filter[ $notice_type ]->callbacks[ $priority ][ $name ] );
							}
							continue;
						}

						// When rules[notice_type] is non‑empty (e.g. admin_footer), remove only specific callbacks.
						$cb = is_array( $fn ) ? $fn[1] : $fn;
						if ( in_array( $cb, $rules[ $notice_type ], true ) ) {
							unset( $wp_filter[ $notice_type ]->callbacks[ $priority ][ $name ] );
						}
					}
				}
			}
		}

		/**
		 * Dispatcher for admin notices (fired once at PHP_INT_MAX on admin_notices).
		 * Ensures CTL notices can be rendered after pruning on timeline addon pages.
		 */
		// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound, WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
		public function ctl_dash_admin_notices() {
			if ( defined( 'CTL_ADMIN_NOTICE_RENDERED' ) ) {
				return;
			}

			define( 'CTL_ADMIN_NOTICE_RENDERED', true );
			

			do_action( 'ctl_display_admin_notices' );
		}
		// phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound, WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound

		/**
		 * On timeline addon pages, inject self-hosted Inter @font-face with absolute URLs
		 * so fonts load on InstaWP/live (avoids relative-path and case-sensitivity issues).
		 * Only injects if font files exist in admin/timeline-addon-page/assets/fonts/ to avoid 404s.
		 */
		public function ctl_enqueue_addon_fonts() {
			if ( ! function_exists( 'ctl_is_timeline_addon_page' ) || ! ctl_is_timeline_addon_page() ) {
				return;
			}
			$font_file    = 'Inter-Regular.woff2';
			$style_handle = 'cool-plugins-timeline-addon';

			// Ensure the main stylesheet is enqueued first.
			if ( ! wp_style_is( $style_handle, 'enqueued' ) && ! wp_style_is( $style_handle, 'registered' ) ) {
				wp_enqueue_style(
					$style_handle,
					CTL_PLUGIN_URL . 'admin/timeline-addon-page/assets/css/styles.css',
					array(),
					CTL_V
				);
			}

			// Try self-hosted fonts: CTLB's directory first (confirmed present on InstaWP),
			// then CTL's own directory.
			$font_url = '';

			if ( defined( 'CTLB_Pro_Dir' ) && defined( 'CTLB_Pro_Url' )
				&& file_exists( CTLB_Pro_Dir . 'admin/timeline-addon-page/assets/fonts/' . $font_file )
			) {
				$font_url = CTLB_Pro_Url . 'admin/timeline-addon-page/assets/fonts/';
			} elseif ( file_exists( CTL_PLUGIN_DIR . 'admin/timeline-addon-page/assets/fonts/' . $font_file ) ) {
				$font_url = CTL_PLUGIN_URL . 'admin/timeline-addon-page/assets/fonts/';
			}

			if ( $font_url ) {
				$safe_font_url = esc_url( $font_url );
				$font_face     = sprintf(
					"@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url('%sInter-Regular.woff2') format('woff2');}\n" .
					"@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url('%sInter-Medium.woff2') format('woff2');}\n" .
					"@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url('%sInter-SemiBold.woff2') format('woff2');}\n" .
					"@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;src:url('%sInter-Bold.woff2') format('woff2');}",
					$safe_font_url,
					$safe_font_url,
					$safe_font_url,
					$safe_font_url
				);
				wp_add_inline_style( $style_handle, $font_face );
			} else {
				// No self-hosted files found – fall back to bunny.net CDN (GDPR-friendly).
				// This guarantees Inter loads on InstaWP / staging without needing font files on disk.
				wp_enqueue_style(
					'cool-plugins-inter-font',
					'https://fonts.bunny.net/css?family=inter:400,500,600,700&display=swap',
					array(),
					CTL_V
				);
			}
		}

		/*
		  Including required files
		*/
		public function ctl_include_files() {
			$this->include_core_files();
			$this->include_shortcode_files();
			$this->include_vc_addon_files();

			if ( is_admin() ) {
				$this->include_admin_files();
			}

			$this->include_block_files();
			$this->include_shortcode_generator_files();
			$this->register_feedback_hooks();
		}

		/**
		 * Include core plugin classes.
		 */
		private function include_core_files() {
			require CTL_PLUGIN_DIR . 'admin/class.cool-timeline-posttype.php';
			require CTL_PLUGIN_DIR . 'includes/class-stories-migration.php';
			require_once CTL_PLUGIN_DIR . 'admin/class-migration.php';
			include_once CTL_PLUGIN_DIR . 'includes/shortcodes/class-ctl-helpers.php';
		}

		/**
		 * Include and initialize shortcode classes.
		 */
		private function include_shortcode_files() {
			require CTL_PLUGIN_DIR . 'includes/shortcodes/class-ctl-settings.php';
			$settings_obj = new CTL_Settings();

			require CTL_PLUGIN_DIR . 'includes/shortcodes/class-ctl-shortcode.php';
			new CTL_Shortcode( $settings_obj );
		}

		/**
		 * Include and initialize Visual Composer addon support.
		 */
		private function include_vc_addon_files() {
			require CTL_PLUGIN_DIR . '/includes/class-cool-vc-addon.php';
		}

		/**
		 * Include admin-only files.
		 */
		private function include_admin_files() {
			require_once CTL_PLUGIN_DIR . 'admin/cpfm-feedback/users-feedback.php';
			require_once CTL_PLUGIN_DIR . 'admin/codestar-framework/codestar-framework.php';
				
			require_once __DIR__ . '/admin/timeline-addon-page/timeline-addon-page.php';
			/*** Plugin review notice file */
			require_once CTL_PLUGIN_DIR . '/admin/notices/admin-notices.php';

			cool_plugins_timeline_addons_settings_page( 'timeline', 'cool-plugins-timeline-addon', 'Timeline Addons', ' Timeline Addons', CTL_PLUGIN_URL . 'assets/images/cool-timeline-icon.svg' );
		}

		/**
		 * Include block editor integration files.
		 */
		private function include_block_files() {
			require CTL_PLUGIN_DIR . 'includes/cool-timeline-block/src/init.php';
		}

		/**
		 * Include shortcode generator files.
		 */
		private function include_shortcode_generator_files() {
			require_once CTL_PLUGIN_DIR . 'admin/ctl-shortcode-generator.php';
		}

		/**
		 * Register feedback hooks after feedback files are available.
		 */
		private function register_feedback_hooks() {
			add_action('cpfm_register_notice', function () {
            
				if (!class_exists('CPFM_Feedback_Notice') || !current_user_can('manage_options')) {
					return;
				}
	
		$notice = [
	
			// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
			'title' => __('Timeline Plugins by Cool Plugins', 'ctl'),
			// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
			'message' => __('Help us make this plugin more compatible with your site by sharing non-sensitive site data.', 'cool-plugins-feedback'),
			'pages' => ['cool_timeline_settings', 'cool-plugins-timeline-addon'],
			'always_show_on' => ['cool_timeline_settings', 'cool-plugins-timeline-addon'],
			'plugin_name'=>'ctl'
		];
	
			
				CPFM_Feedback_Notice::cpfm_register_notice('cool-timeline', $notice);
	
					if (!isset($GLOBALS['cool_plugins_feedback'])) {
						$GLOBALS['cool_plugins_feedback'] = [];
					}
					
				
					$GLOBALS['cool_plugins_feedback']['cool-timeline'][] = $notice;
		   
			});
			add_action('cpfm_after_opt_in_ctl', function($category){
			

				if ($category === 'cool-timeline') {
					$data = get_option('cool_timeline_settings'); 
					$data['ctl_cpfm_feedback_data'] = true;
			update_option('cool_timeline_settings', $data);
		
					if(class_exists('CTL_CRONJOB')){
						CTL_CRONJOB::ctl_send_data();
					}
				}
			});
		}



		// flush rewrite rules after activation
		public function ctl_flush_rules() {
			if ( get_option( 'ctl_flush_rewrite_rules_flag' ) ) {
				flush_rewrite_rules();
				delete_option( 'ctl_flush_rewrite_rules_flag' );
			}
		}

		// Initialize plugin options and admin settings files.
		public function ctl_maybe_init_plugin_options() {

			$this->ctl_init_install_options();

			if ( is_admin() ) {
				
				require_once CTL_PLUGIN_DIR . 'admin/ctl-admin-settings.php';
				require CTL_PLUGIN_DIR . 'admin/ctl-meta-fields.php';

				
			}
		}

		/**
		 * Initialize install/version options when they do not already exist.
		 */
		private function ctl_init_install_options() {
			if ( ! get_option( 'ctl_initial_save_version' ) ) {
				add_option( 'ctl_initial_save_version', CTL_V );
			}

			if ( ! get_option( 'ctl-install-date' ) ) {
				add_option( 'ctl-install-date', gmdate( 'Y-m-d h:i:s' ) );
			}
		}

		public function ctl_plugin_redirection( $plugin ) {
			if ( plugin_basename( __FILE__ ) === $plugin ) {
				wp_safe_redirect( admin_url( 'admin.php?page=cool_timeline_settings#tab=get-started' ) );
				exit;
			}
		}

		// Add the settings link to the plugins page
		public function ctl_settings_link( $links ) {
			array_unshift( $links, '<a href="admin.php?page=cool_timeline_settings">Settings</a>' );
			$links[] = '<a style="font-weight:bold; color:#852636;" href="https://cooltimeline.com/plugin/cool-timeline-pro/?utm_source=ctl_plugin&utm_medium=inside&utm_campaign=get_pro&utm_content=plugins_list" target="_blank">Get Pro</a>';

			return $links;
		}

		/**
		 * Save post metadata when a story is saved.
		 *
		 * @param int  $post_id The post ID.
		 * @param post $post The post object.
		 * @param bool $update Whether this is an existing post being updated or not.
		 */
		public function ctl_save_story_meta( $post_id, $post, $update ) {
			// Bail on autosaves/revisions.
			if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
				return;
			}

			// If this isn't a 'cool_timeline' post, don't update it.
			$post_type = get_post_type( $post_id );
			if ( 'cool_timeline' !== $post_type ) {
				return;
			}

			// Permission check.
			if ( ! current_user_can( 'edit_post', $post_id ) ) {
				return;
			}

			$story_date = '';

			/**
			 * Prefer using posted metabox value when a valid WP core post nonce exists.
			 * This avoids relying on a custom nonce that may not be present in all editors/requests.
			 */
			// phpcs:ignore WordPress.Security.NonceVerification.Missing
			if ( isset( $_POST['_wpnonce'] ) ) {
				$wp_nonce = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) );
				if ( wp_verify_nonce( $wp_nonce, 'update-post_' . $post_id ) ) {
					// phpcs:ignore WordPress.Security.NonceVerification.Missing
					if ( isset( $_POST['ctl_post_meta']['story_type']['ctl_story_date'] ) ) {
						// phpcs:ignore WordPress.Security.NonceVerification.Missing
						$story_date = sanitize_text_field( wp_unslash( $_POST['ctl_post_meta']['story_type']['ctl_story_date'] ) );
					}
				}
			}

			// Fallback: read already-saved metabox meta (works for REST/Gutenberg flows too).
			if ( empty( $story_date ) ) {
				$ctl_post_meta = get_post_meta( $post_id, 'ctl_post_meta', true );
				if ( is_array( $ctl_post_meta ) && isset( $ctl_post_meta['story_type']['ctl_story_date'] ) ) {
					$story_date = sanitize_text_field( $ctl_post_meta['story_type']['ctl_story_date'] );
				}
			}

			// Fallback: read legacy/meta fields if present.
			if ( empty( $story_date ) ) {
				$story_date = sanitize_text_field( (string) get_post_meta( $post_id, 'ctl_story_date', true ) );
			}

			if ( ! empty( $story_date ) ) {
				$story_timestamp = CTL_Helpers::ctlfree_generate_custom_timestamp( $story_date );
				update_post_meta( $post_id, 'ctl_story_timestamp', $story_timestamp );
				update_post_meta( $post_id, 'story_based_on', 'default' );
				update_post_meta( $post_id, 'ctl_story_date', $story_date );
			}

		}



		/*
		* Fixed Bridge theme confliction
		*/
		public function ctl_deregister_javascript() {
			if ( is_admin() ) {
				global $post;

				// phpcs:ignore WordPress.Security.NonceVerification.Missing
				$current_page  = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
				$allowed_pages = array(
					'cool_timeline_settings',
					'cool-plugins-timeline-addon',
					'timeline-addons-license',
				);
				
				if ( !empty( $current_page ) && in_array( $current_page, $allowed_pages, true ) && function_exists( 'wp_deregister_script' ) ) {
					wp_deregister_script( 'default' );
				}

				if ( isset( $post ) && isset( $post->post_type ) && $post->post_type === 'cool_timeline' ) {
					wp_deregister_script( 'acf-timepicker' );
					wp_deregister_script( 'jquery-ui-timepicker-js' );
					wp_deregister_script( 'thrive-admin-datetime-picker' ); // datepicker conflict with Rise theme
					wp_deregister_script( 'et_bfb_admin_date_addon_js' ); // datepicker conflict with Divi theme
					wp_deregister_script( 'zeen-engine-admin-vendors-js' ); // datepicker conflict with zeen engine plugin
				}
			}
		}

		/* Activating plugin and adding some info */
		public function ctl_activate() {

			update_option( 'cool-free-timeline-v', CTL_V );
			update_option( 'cool-timelne-plugin-type', 'FREE' );
			update_option( 'cool-timelne-installDate', gmdate( 'Y-m-d h:i:s' ) );
			update_option( 'cool-timeline-already-rated', 'no' );
			update_option( 'ctl_flush_rewrite_rules_flag', true );



			$this->ctl_init_install_options();

			if ( $this->ctl_is_tracking_enabled() ) {
				$this->ctl_maybe_schedule_tracking_cron();
			}
	}

		/* Deactivate the plugin */
		public function ctl_deactivate() {
			if (wp_next_scheduled('ctl_extra_data_update')) {
				wp_clear_scheduled_hook('ctl_extra_data_update');
			}
		}

	public static function ctl_get_user_info() {

		global $wpdb;
	
		// Server and WP environment details

		$server_info = [

		'server_software'        => isset($_SERVER['SERVER_SOFTWARE']) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : 'N/A',
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			'mysql_version'          => $wpdb ? sanitize_text_field( $wpdb->get_var( 'SELECT VERSION()' ) ) : 'N/A',
			'php_version'            => sanitize_text_field(phpversion() ?: 'N/A'),
			'wp_version'             => sanitize_text_field(get_bloginfo('version') ?: 'N/A'),
			'wp_debug'               => (defined('WP_DEBUG') && WP_DEBUG) ? 'Enabled' : 'Disabled',
			'wp_memory_limit'        => sanitize_text_field(ini_get('memory_limit') ?: 'N/A'),
			'wp_max_upload_size'     => sanitize_text_field(ini_get('upload_max_filesize') ?: 'N/A'),
			'wp_permalink_structure' => sanitize_text_field(get_option('permalink_structure') ?: 'Default'),
			'wp_multisite'           => is_multisite() ? 'Enabled' : 'Disabled',
			'wp_language'            => sanitize_text_field(get_option('WPLANG') ?: get_locale()),
			'wp_prefix'              => isset($wpdb->prefix) ? sanitize_key($wpdb->prefix) : 'N/A',
		];
	
		// Theme details
		$theme = wp_get_theme();
		$theme_data = [
			'name'      => sanitize_text_field($theme->get('Name')),
			'version'   => sanitize_text_field($theme->get('Version')),
			'theme_uri' => esc_url($theme->get('ThemeURI')),
		];
	

		if (!function_exists('get_plugins')) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}
		if (!function_exists('get_plugin_data')) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}
	

		$plugin_data = [];
		$active_plugins = get_option('active_plugins', []);
	
		foreach ($active_plugins as $plugin_path) {
			$plugin_file = WP_PLUGIN_DIR . '/' . ltrim($plugin_path, '/');
	
			if (file_exists($plugin_file)) {

				$plugin_info = get_plugin_data($plugin_file, false, false);
				$plugin_url = !empty($plugin_info['PluginURI']) ? esc_url($plugin_info['PluginURI']) : (!empty($plugin_info['AuthorURI']) ? esc_url($plugin_info['AuthorURI']) : 'N/A');
				$plugin_data[] = [
					'name'       => sanitize_text_field($plugin_info['Name']),
					'version'    => sanitize_text_field($plugin_info['Version']),
					'plugin_uri' => !empty($plugin_url) ? $plugin_url : 'N/A',
				];
			}
		}
	
		return [
			'server_info'   => $server_info,
			'extra_details' => [
				'wp_theme'       => $theme_data,
				'active_plugins' => $plugin_data,
			],
		];
	}
	
	}
}

/*** THANKS - CoolPlugins.net ) */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
$ctl = CoolTimeline::get_instance();
$ctl->registers();

