文件操作 - cooltimeline.php
返回文件管理
返回主菜单
删除本文件
文件: /storage/v12552/jimbrandstatter/public_html/wp-content/plugins/cool-timeline/cooltimeline.php
编辑文件内容
<?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.4 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.4' ); } // 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; } // Installation and uninstallation hooks register_activation_hook( __FILE__, array( $thisIns, 'ctl_activate' ) ); register_deactivation_hook( __FILE__, array( $thisIns, 'ctl_deactivate' ) ); add_action( 'activated_plugin', array( $thisIns, 'ctl_plugin_redirection' ) ); /* including required files */ add_action( 'plugins_loaded', array( $thisIns, 'ctl_include_files' ) ); add_action( 'init', array( $thisIns, 'ctl_flush_rules' ) ); // loading plugin translation files add_action( 'init', array( $thisIns, 'ctl_load_plugin_textdomain' ) ); // Cool Timeline all hooks integrations if ( is_admin() ) { $pluginpath = plugin_basename( __FILE__ ); // plugin settings links hook add_filter( "plugin_action_links_$pluginpath", array( $thisIns, 'ctl_settings_link' ) ); // save extra story meta for timeline sorting add_action( 'save_post', array( $thisIns, 'ctl_save_story_meta' ), 10, 3 ); require_once plugin_dir_path( __FILE__ ) . 'admin/marketing/ctl-marketing.php'; add_action( 'admin_menu', array( $thisIns, 'ctl_add_new_item' ) ); add_action( 'admin_print_scripts', array( $thisIns, 'ctl_hide_unrelated_notices' ), 999 ); add_action( 'admin_enqueue_scripts', array( $thisIns, 'ctl_enqueue_addon_fonts' ), 20 ); } // Fixed bridge theme confliction using this action hook add_action( 'wp_print_scripts', array( $thisIns, 'ctl_deregister_javascript' ), 100 ); // gutenberg block integartion 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(){ $data = get_option('cool_timeline_settings'); $opt_in = !empty($data['ctl_cpfm_feedback_data']) ? $data['ctl_cpfm_feedback_data']:''; if (!empty($opt_in)) { if(!wp_next_scheduled('ctl_extra_data_update')){ wp_schedule_event(time(), 'every_30_days', 'ctl_extra_data_update'); } }else { if (wp_next_scheduled('ctl_extra_data_update')) { wp_clear_scheduled_hook('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 (if present), then CTL's own directory. if ( defined( 'CTLB_Pro_Dir' ) && defined( 'CTLB_Pro_Url' ) && file_exists( CTLB_Pro_Dir . 'admin/timeline-addon-page/assets/fonts/' . $font_file ) ) { $base = CTLB_Pro_Url . 'admin/timeline-addon-page/assets/'; $font_url = $base . 'fonts/'; $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');}", esc_url( $font_url ), esc_url( $font_url ), esc_url( $font_url ), esc_url( $font_url ) ); wp_add_inline_style( $style_handle, $font_face ); } elseif ( file_exists( CTL_PLUGIN_DIR . 'admin/timeline-addon-page/assets/fonts/' . $font_file ) ) { $base = CTL_PLUGIN_URL . 'admin/timeline-addon-page/assets/'; $font_url = $base . 'fonts/'; $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');}", esc_url( $font_url ), esc_url( $font_url ), esc_url( $font_url ), esc_url( $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() { // register cool-timeline post type 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'; // contains helper funciton for timeline include_once CTL_PLUGIN_DIR . 'includes/shortcodes/class-ctl-helpers.php'; // Cool Timeline Src New Shortcode require CTL_PLUGIN_DIR . 'includes/shortcodes/class-ctl-settings.php'; $settings_obj = new CTL_Settings(); // Cool Timeline Src New Shortcode require CTL_PLUGIN_DIR . 'includes/shortcodes/class-ctl-shortcode.php'; new CTL_Shortcode( $settings_obj ); // VC addon support require CTL_PLUGIN_DIR . '/includes/class-cool-vc-addon.php'; new CoolTmVCAddon(); /* Loaded Backend files only */ if ( is_admin() ) { require_once CTL_PLUGIN_DIR . 'admin/cpfm-feedback/users-feedback.php'; // including timeline stories meta boxes class require_once CTL_PLUGIN_DIR . 'admin/codestar-framework/codestar-framework.php'; require_once CTL_PLUGIN_DIR . 'admin/cpfm-feedback/users-feedback.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' ); } require CTL_PLUGIN_DIR . 'includes/cool-timeline-block/src/init.php'; require_once CTL_PLUGIN_DIR . 'admin/ctl-shortcode-generator.php'; 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); require_once __DIR__ . '/includes/cron/class-cron.php'; 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' ); } } // loading language files public function ctl_load_plugin_textdomain() { 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') ); } if ( is_admin() ) { require_once CTL_PLUGIN_DIR . 'admin/ctl-admin-settings.php'; require CTL_PLUGIN_DIR . 'admin/ctl-meta-fields.php'; } } 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( 'acf-input' ); // datepicker translaton issue // wp_deregister_script( 'acf' ); // datepicker translaton issue 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 } } } public static function is_theme_activate( $target ) { $theme = wp_get_theme(); if ( $theme->name === $target || stripos( $theme->parent_theme, $target ) !== false ) { return true; } return false; } /* 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 ); 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') ); } $data = get_option('cool_timeline_settings'); $opt_in = !empty($data['ctl_cpfm_feedback_data']) ? $data['ctl_cpfm_feedback_data']:''; if($opt_in){ if (!wp_next_scheduled('ctl_extra_data_update')) { wp_schedule_event(time(), 'every_30_days', 'ctl_extra_data_update'); } } } /* 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();
修改文件时间
将文件时间修改为当前时间的前一年
删除文件