prefix . 'astr_plugins_history'; $table_safe = esc_sql($table); // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->query("DROP TABLE IF EXISTS {$table_safe}");// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery } delete_option( 'astr_delete_on_uninstall' ); } add_filter( 'upgrader_pre_install', 'astr_save_all_plugin_versions_before_install', 10, 2 ); function astr_save_all_plugin_versions_before_install( $true, $hook_extra ) { global $astr_all_plugins_versions_before_update; if ( ( isset( $hook_extra['type'] ) && $hook_extra['type'] == 'plugin' ) || isset( $hook_extra['plugin'] ) ) { $installed_plugins = get_plugins(); $astr_all_plugins_versions_before_update = $installed_plugins; } return $true; } add_action( 'activated_plugin', 'astr_plugins_activated', 10, 2 ); add_filter('upgrader_post_install', 'astr_handle_plugin_post_install', 10, 3); function astr_handle_plugin_post_install($response, $hook_extra, $result) { global $wpdb; global $astr_all_plugins_versions_before_update; $table = $wpdb->prefix . 'astr_plugins_history'; if ((isset($hook_extra['type']) && $hook_extra['type'] == 'plugin') || isset($hook_extra['plugin'])) { $current_user = wp_get_current_user(); if (defined('WP_CLI') && WP_CLI) { $user_id = 0; $os_user = astr_get_os_username(); $user_name = 'WP-CLI (' . $os_user . ')'; } else { $user_id = $current_user->ID; $user_name = $user_id ? $current_user->display_name : 'Automatic Update'; } if (isset($result['destination'])) { $plugin_dir = $result['destination']; } else { $plugin_dir = WP_PLUGIN_DIR . '/' . dirname($hook_extra['plugin']); } $plugin_dir = wp_normalize_path($plugin_dir); $plugin_slug = basename($plugin_dir); $plugin_files = glob($plugin_dir . '/*.php'); if ($plugin_files) { foreach ($plugin_files as $plugin_file) { $plugin_file = wp_normalize_path($plugin_file); $plugin_data = get_plugin_data($plugin_file); if (!empty($plugin_data['Name'])) { $relative_plugin_file = str_replace(wp_normalize_path(WP_PLUGIN_DIR) . '/', '', $plugin_file); $old_version = 'Not installed'; if (isset($astr_all_plugins_versions_before_update[$relative_plugin_file])) { $old_version = $astr_all_plugins_versions_before_update[$relative_plugin_file]['Version']; } $new_version = $plugin_data['Version']; $action = ($old_version == 'Not installed') ? 'installed' : 'updated'; if ($action === 'installed') { astr_add_event_to_buffer($plugin_data['Name'], 'installed', $user_name); } if ($action === 'updated') { astr_add_event_to_buffer( $plugin_data['Name'], 'updated', $user_name, $old_version, $new_version ); } if ($action === 'installed') { // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $exists = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$table} WHERE plugin_path = %s", $relative_plugin_file ) ); if (!$exists) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $table, array( 'plugin_path' => $relative_plugin_file, 'plugin_name' => $plugin_data['Name'], 'user_id' => $user_id, 'user_name' => $user_name, 'action' => 'tracking_started', 'time' => current_time('mysql'), 'extra_info' => astr_get_extended_cli_info(), ) ); } } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $table, array( 'plugin_path' => $relative_plugin_file, 'plugin_name' => $plugin_data['Name'], 'user_id' => $user_id, 'user_name' => $user_name, 'action' => $action, 'time' => current_time('mysql'), 'old_version' => ($action == 'updated') ? $old_version : null, 'new_version' => $new_version, 'extra_info' => astr_get_extended_cli_info(), ), array('%s','%s','%d','%s','%s','%s','%s','%s','%s') ); break; } } } } return $response; } function astr_add_plugin_version_history_event( $plugin_file, $old_version, $new_version, $user_name ) { global $wpdb; $table = $wpdb->prefix . 'astr_plugins_history'; $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_file ); if ( empty( $plugin_data['Name'] ) ) { return; } if ( version_compare( $new_version, $old_version, '>' ) ) { $action = 'updated'; } elseif ( version_compare( $new_version, $old_version, '<' ) ) { $action = 'rolled_back'; } else { $action = 'installed'; } $wpdb->insert( $table, array( 'plugin_path' => $plugin_file, 'plugin_name' => $plugin_data['Name'], 'user_id' => get_current_user_id(), 'user_name' => $user_name, 'action' => $action, 'time' => current_time( 'mysql' ), 'old_version' => $old_version, 'new_version' => $new_version, 'extra_info' => null, ), array( '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s' ) ); astr_add_event_to_buffer( $plugin_data['Name'], $action, $user_name, $old_version, $new_version ); } function astr_plugins_activated( $plugin, $network_wide ) { if ( get_transient( 'astr_version_installing' ) ) { return; } global $wpdb; $table = $wpdb->prefix . 'astr_plugins_history'; $current_user = wp_get_current_user(); if ( defined( 'WP_CLI' ) && WP_CLI ) { $user_id = 0; $os_user = astr_get_os_username(); $user_name = 'WP-CLI (' . $os_user . ')'; } else { $user_id = $current_user->ID; $user_name = $current_user->display_name; } $plugin_base_name = plugin_basename( $plugin ); $all_plugins = get_plugins(); $plugin_name = isset( $all_plugins[ $plugin_base_name ]['Name'] ) ? $all_plugins[ $plugin_base_name ]['Name'] : $plugin_base_name; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $table, array( 'plugin_path' => $plugin_base_name, 'plugin_name' => $plugin_name, 'user_id' => $user_id, 'user_name' => $user_name, 'action' => 'activated', 'time' => current_time( 'mysql' ), 'extra_info' => astr_get_extended_cli_info(), ), array( '%s', '%s', '%d', '%s', '%s', '%s', '%s' ) ); if ( $plugin_base_name === 'adwise-sitetrace/adwise-sitetrace.php' ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $table, array( 'plugin_path' => $plugin_base_name, 'plugin_name' => $plugin_name, 'user_id' => $user_id, 'user_name' => $user_name, 'action' => 'tracking_started', 'time' => current_time( 'mysql' ), 'extra_info' => astr_get_extended_cli_info(), ), array( '%s', '%s', '%d', '%s', '%s', '%s', '%s' ) ); } astr_add_event_to_buffer( $plugin_name, 'activated', $user_name ); } add_action( 'deactivated_plugin', 'astr_plugins_deactivated', 10, 2 ); function astr_plugins_deactivated( $plugin, $network_wide ) { if ( get_transient( 'astr_version_installing' ) ) { return; } global $wpdb; $table = $wpdb->prefix . 'astr_plugins_history'; $current_user = wp_get_current_user(); if ( defined( 'WP_CLI' ) && WP_CLI ) { $user_id = 0; $os_user = astr_get_os_username(); $user_name = 'WP-CLI (' . $os_user . ')'; } else { $user_id = $current_user->ID; $user_name = $current_user->display_name; } $plugin_base_name = plugin_basename( $plugin ); $all_plugins = get_plugins(); $plugin_name = isset( $all_plugins[ $plugin_base_name ]['Name'] ) ? $all_plugins[ $plugin_base_name ]['Name'] : $plugin_base_name; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $table, array( 'plugin_path' => $plugin_base_name, 'plugin_name' => $plugin_name, 'user_id' => $user_id, 'user_name' => $user_name, 'action' => 'deactivated', 'time' => current_time( 'mysql' ), 'extra_info' => astr_get_extended_cli_info(), ), array( '%s', '%s', '%d', '%s', '%s', '%s', '%s' ) ); if ( $plugin_base_name === 'adwise-sitetrace/adwise-sitetrace.php' ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $table, array( 'plugin_path' => $plugin_base_name, 'plugin_name' => $plugin_name, 'user_id' => $user_id, 'user_name' => $user_name, 'action' => 'tracking_stopped', 'time' => current_time( 'mysql' ), 'extra_info' => astr_get_extended_cli_info(), ), array( '%s', '%s', '%d', '%s', '%s', '%s', '%s' ) ); } astr_add_event_to_buffer( $plugin_name, 'deactivated', $user_name ); } add_action( 'deleted_plugin', 'astr_plugin_deleted', 10, 1 ); function astr_plugin_deleted( $plugin ) { global $wpdb; $table = $wpdb->prefix . 'astr_plugins_history'; $current_user = wp_get_current_user(); if ( defined( 'WP_CLI' ) && WP_CLI ) { $user_id = 0; $os_user = astr_get_os_username(); $user_name = 'WP-CLI (' . $os_user . ')'; } else { $user_id = $current_user->ID; $user_name = $current_user->display_name; } $plugin_base_name = plugin_basename( $plugin ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $plugin_name = $wpdb->get_var( $wpdb->prepare( "SELECT plugin_name FROM {$wpdb->prefix}astr_plugins_history WHERE plugin_path = %s ORDER BY time DESC LIMIT 1", $plugin ) ); if ( empty( $plugin_name ) ) { $plugin_name = ucwords( str_replace( array( '-', '_' ), ' ', dirname( $plugin_base_name ) !== '.' ? dirname( $plugin_base_name ) : basename( $plugin_base_name, '.php' ) ) ); } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $table, array( 'plugin_path' => $plugin_base_name, 'plugin_name' => $plugin_name, 'user_id' => $user_id, 'user_name' => $user_name, 'action' => 'removed', 'time' => current_time( 'mysql' ), 'extra_info' => astr_get_extended_cli_info(), ), array( '%s', '%s', '%d', '%s', '%s', '%s', '%s' ) ); astr_add_event_to_buffer( $plugin_name, 'removed', $user_name ); } add_filter( 'upgrader_pre_install', 'astr_store_plugins_versions_before_update', 5, 2 ); function astr_store_plugins_versions_before_update( $response, $hook_extra ) { if ( empty( $hook_extra['type'] ) || $hook_extra['type'] !== 'plugin' ) { return; } global $astr_all_plugins_versions_before_update; $plugins = []; if ( ! empty( $hook_extra['plugins'] ) ) { $plugins = $hook_extra['plugins']; } elseif ( ! empty( $hook_extra['plugin'] ) ) { $plugins = [ $hook_extra['plugin'] ]; } foreach ( $plugins as $plugin_file ) { $all_plugins = get_plugins(); if ( isset( $all_plugins[ $plugin_file ]['Version'] ) ) { $astr_all_plugins_versions_before_update[ $plugin_file ] = [ 'Version' => $all_plugins[ $plugin_file ]['Version'] ]; } } return $response; } function astr_plugins_history_tracking_started() { global $wpdb; $table = $wpdb->prefix . 'astr_plugins_history'; $all_plugins = get_plugins(); $current_user = wp_get_current_user(); $user_id = $current_user->ID ?? 0; $user_name = $current_user->display_name ?? 'System'; foreach ( $all_plugins as $plugin_path => $data ) { if ( $plugin_path === 'adwise-sitetrace/adwise-sitetrace.php' ) { continue; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $table, array( 'plugin_path' => $plugin_path, 'plugin_name' => $data['Name'] ?? $plugin_path, 'user_id' => $user_id, 'user_name' => $user_name, 'action' => 'tracking_started', 'time' => current_time( 'mysql' ), 'old_version' => null, 'new_version' => $data['Version'] ?? null, 'extra_info' => null, ), array( '%s','%s','%d','%s','%s','%s','%s','%s','%s' ) ); } //Plugins from history that are no longer installed. $installed_plugins = array_keys( $all_plugins ); $history_plugins = $wpdb->get_results( $wpdb->prepare( "SELECT plugin_path, plugin_name FROM {$table} WHERE plugin_path <> %s GROUP BY plugin_path", 'adwise-sitetrace/adwise-sitetrace.php' ) ); foreach ( $history_plugins as $plugin ) { if ( in_array( $plugin->plugin_path, $installed_plugins, true ) ) { continue; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $table, array( 'plugin_path' => $plugin->plugin_path, 'plugin_name' => $plugin->plugin_name, 'user_id' => $user_id, 'user_name' => $user_name, 'action' => 'tracking_started', 'time' => current_time( 'mysql' ), 'old_version' => null, 'new_version' => $data['Version'] ?? null, 'extra_info' => null, ), array( '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s' ) ); } } function astr_plugins_history_tracking_stopped() { global $wpdb; $table = $wpdb->prefix . 'astr_plugins_history'; $all_plugins = get_plugins(); $current_user = wp_get_current_user(); $user_id = $current_user->ID ?? 0; $user_name = $current_user->display_name ?? 'System'; foreach ( $all_plugins as $plugin_path => $data ) { if ( $plugin_path === 'adwise-sitetrace/adwise-sitetrace.php' ) { continue; } // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.NoCaching $exists = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$table} WHERE plugin_path = %s LIMIT 1", $plugin_path ) ); if ( ! $exists ) { continue; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $table, array( 'plugin_path' => $plugin_path, 'plugin_name' => $data['Name'] ?? $plugin_path, 'user_id' => $user_id, 'user_name' => $user_name, 'action' => 'tracking_stopped', 'time' => current_time( 'mysql' ), 'old_version' => null, 'new_version' => $data['Version'] ?? null, 'extra_info' => null, ), array( '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s' ) ); } //Plugins from history that are no longer installed. $installed_plugins = array_keys( $all_plugins ); $history_plugins = $wpdb->get_results( $wpdb->prepare( "SELECT plugin_path, plugin_name FROM {$table} WHERE plugin_path <> %s GROUP BY plugin_path", 'adwise-sitetrace/adwise-sitetrace.php' ) ); foreach ( $history_plugins as $plugin ) { if ( in_array( $plugin->plugin_path, $installed_plugins, true ) ) { continue; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $table, array( 'plugin_path' => $plugin->plugin_path, 'plugin_name' => $plugin->plugin_name, 'user_id' => $user_id, 'user_name' => $user_name, 'action' => 'tracking_stopped', 'time' => current_time( 'mysql' ), 'old_version' => null, 'new_version' => $data['Version'] ?? null, 'extra_info' => null, ), array( '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s' ) ); } } add_action( 'admin_init', 'astr_handle_history_page_actions' ); function astr_handle_history_page_actions() { if ( ! is_admin() ) { return; } $history_page_url = admin_url( 'admin.php?page=astr-plugins-history' ); if ( isset( $_GET['plugin'] ) && 'adwise-sitetrace/adwise-sitetrace.php' === sanitize_text_field( wp_unslash( $_GET['plugin'] ) ) ) { $history_page_url = admin_url( 'plugins.php' ); } if ( isset( $_POST['astr_pause_plugin'] ) || ( isset( $_POST['plugin'] ) && isset( $_POST['_wpnonce'] ) && isset( $_POST['_wp_http_referer'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'astr_pause_plugin_action' ) && ! isset( $_POST['astr_install_plugin_version'] ) ) ) { check_admin_referer('astr_pause_plugin_action'); $plugin = sanitize_text_field( wp_unslash( $_POST['plugin'] ) ); $plugins = get_option('astr_paused_plugin_updates', array()); if (isset($_POST['astr_pause_plugin'])) { $plugins[$plugin] = true; } else { unset($plugins[$plugin]); } update_option('astr_paused_plugin_updates', $plugins); wp_safe_redirect( $history_page_url ); exit; } if ( isset( $_GET['astr_action'], $_GET['plugin'] ) ) { check_admin_referer( 'astr-plugin-action' ); $plugin = sanitize_text_field( wp_unslash( $_GET['plugin'] ) ); $all_plugins = get_plugins(); $plugin_name = isset( $all_plugins[ $plugin ]['Name'] ) ? $all_plugins[ $plugin ]['Name'] : $plugin; $notice_type = ''; if ( $_GET['astr_action'] === 'activate' ) { if ( ! current_user_can( 'activate_plugins' ) ) { wp_die( esc_html__( 'Sorry, you are not allowed to activate plugins.', 'adwise-sitetrace' ) ); } $result = activate_plugin( $plugin, '', false, true ); if ( is_wp_error( $result ) ) { wp_die( esc_html( $result->get_error_message() ) ); } // The activation hook is skipped because the plugin is activated silently. // Record the activation event manually. astr_plugins_activated( $plugin, false ); $notice_type = 'activated'; } if ( $_GET['astr_action'] === 'deactivate' ) { if ( ! current_user_can( 'activate_plugins' ) ) { wp_die( esc_html__( 'Sorry, you are not allowed to deactivate plugins.', 'adwise-sitetrace' ) ); } deactivate_plugins( $plugin ); $notice_type = 'deactivated'; } if ( $_GET['astr_action'] === 'delete' ) { if ( ! current_user_can( 'delete_plugins' ) ) { wp_die( esc_html__( 'Sorry, you are not allowed to delete plugins.', 'adwise-sitetrace' ) ); } if ( is_plugin_active( $plugin ) ) { if ( ! current_user_can( 'activate_plugins' ) ) { wp_die( esc_html__( 'Sorry, you are not allowed to deactivate plugins.', 'adwise-sitetrace' ) ); } deactivate_plugins( $plugin ); } require_once ABSPATH . 'wp-admin/includes/plugin.php'; require_once ABSPATH . 'wp-admin/includes/file.php'; $deleted = delete_plugins( array( $plugin ) ); if ( is_wp_error( $deleted ) ) { $notice_type = 'delete_error'; } else { $notice_type = 'deleted'; } } wp_safe_redirect( add_query_arg( array( 'astr_notice' => $notice_type, 'plugin_name' => rawurlencode( $plugin_name ), ), $history_page_url ) ); exit; } if ( isset( $_POST['astr_install_plugin_version'] ) ) { check_admin_referer( 'astr_install_plugin_version' ); if ( ! current_user_can( 'install_plugins' ) ) { wp_die( esc_html__( 'Sorry, you are not allowed to install plugins.', 'adwise-sitetrace' ) ); } if ( function_exists( 'set_time_limit' ) ) { // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged @set_time_limit( 300 ); } $plugin = sanitize_text_field( wp_unslash( $_POST['plugin'] ) ); if ( 'adwise-sitetrace/adwise-sitetrace.php' === $plugin ) { $history_page_url = admin_url( 'plugins.php' ); } $slug = isset( $_POST['plugin_slug'] ) ? sanitize_text_field( wp_unslash( $_POST['plugin_slug'] ) ) : ''; $version = isset( $_POST['plugin_version'] ) ? sanitize_text_field( wp_unslash( $_POST['plugin_version'] ) ) : ''; $plugins = get_plugins(); $current_version = $plugins[ $plugin ]['Version'] ?? ''; if ( $current_version === $version ) { $plugin_name = $plugins[ $plugin ]['Name'] ?? $slug; wp_safe_redirect( add_query_arg( array( 'install_version' => 'same', 'plugin_name' => $plugin_name, 'plugin_version' => $version, ), $history_page_url ) ); exit; } $plugins = get_plugins(); $plugin_name = isset( $plugins[ $plugin ]['Name'] ) ? $plugins[ $plugin ]['Name'] : $slug; $download_url = sprintf( 'https://downloads.wordpress.org/plugin/%s.%s.zip', $slug, $version ); require_once ABSPATH . 'wp-admin/includes/file.php'; $temp_file = download_url( $download_url ); if ( is_wp_error( $temp_file ) ) { wp_safe_redirect( add_query_arg( array( 'install_version' => 'error', 'message' => rawurlencode( $temp_file->get_error_message() ), ), $history_page_url ) ); exit; } global $wp_filesystem; WP_Filesystem(); $unzip_dir = get_temp_dir() . 'astr-test-plugin'; if ( $wp_filesystem->exists( $unzip_dir ) ) { $wp_filesystem->delete( $unzip_dir, true ); } wp_mkdir_p( $unzip_dir ); $result = unzip_file( $temp_file, $unzip_dir ); if ( is_wp_error( $result ) ) { wp_safe_redirect( add_query_arg( array( 'install_version' => 'error', 'message' => rawurlencode( $result->get_error_message() ), ), $history_page_url ) ); exit; } $source = trailingslashit( $unzip_dir ) . $slug; // If the archive contains an extra nested folder with the same name, // use it as the actual source directory. $nested_source = trailingslashit( $source ) . $slug; if ( is_dir( $nested_source ) ) { $source = $nested_source; } $destination = trailingslashit( WP_PLUGIN_DIR ) . $slug; $old_plugin_file = $plugin; $old_plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); $old_version = $old_plugin_data['Version'] ?? 'Not installed'; $backup = $destination . '-backup'; $was_active = is_plugin_active( $plugin ); if ( $was_active ) { set_transient( 'astr_version_installing', true, 60 ); deactivate_plugins( $plugin ); } if ( $wp_filesystem->exists( $backup ) ) { $wp_filesystem->delete( $backup, true ); } if ( $wp_filesystem->exists( $destination ) ) { $wp_filesystem->move( $destination, $backup ); } // phpcs:ignore PluginCheck.CodeAnalysis.WriteFile.PluginDirectoryWrite -- Used intentionally to install/restore a selected plugin version into the plugin directory. $result = copy_dir( $source, $destination ); if ( is_wp_error( $result ) ) { if ( $wp_filesystem->exists( $destination ) ) { $wp_filesystem->delete( $destination, true ); } if ( $wp_filesystem->exists( $backup ) ) { $wp_filesystem->move( $backup, $destination ); } wp_safe_redirect( add_query_arg( array( 'install_version' => 'error', 'message' => rawurlencode( $result->get_error_message() ), ), $history_page_url ) ); exit; } if ( $wp_filesystem->exists( $backup ) ) { $wp_filesystem->delete( $backup, true ); } $new_plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); $new_version = $new_plugin_data['Version'] ?? ''; $current_user = wp_get_current_user(); astr_add_plugin_version_history_event( $plugin, $old_version, $new_version, $current_user->display_name ); if ( $was_active && current_user_can( 'activate_plugins' ) ) { activate_plugin( $plugin ); } delete_transient( 'astr_version_installing' ); $wp_filesystem->delete( $unzip_dir, true ); if ( file_exists( $temp_file ) ) { wp_delete_file( $temp_file ); } wp_safe_redirect( add_query_arg( array( 'install_version' => 'success', 'plugin_name' => $plugin_name, 'plugin_version' => $version, ), $history_page_url ) ); exit; } } function astr_plugins_history_page() { $active = astr_get_current_admin_page(); astr_render_admin_tabs( $active ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( isset( $_GET['install_version'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( isset( $_GET['install_version'] ) && 'success' === $_GET['install_version'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $plugin_name = sanitize_text_field( wp_unslash( $_GET['plugin_name'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended $plugin_version = sanitize_text_field( wp_unslash( $_GET['plugin_version'] ?? '' ) ); ?>

prefix . 'astr_plugins_history'; $search_query = astr_safe_get('s', 'text', '', 'manage_options', false); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $results = $wpdb->get_results( "SELECT * FROM {$table} WHERE 1=1 ORDER BY id DESC" ); // Filter by Status $status_filter = astr_safe_get('filter_status', 'text', '', 'manage_options', false); if ($status_filter !== '') { $status_filter = astr_safe_get( 'filter_status' ); $results = array_filter($results, function($r) use ($status_filter) { return strtolower($r->action) === strtolower($status_filter); }); } // Filter by Date $date_filter = astr_safe_get('filter_date', 'text', '', 'manage_options', false); if ($date_filter !== '') { $start = strtotime($date_filter . '-01 00:00:00'); $end = strtotime(gmdate('Y-m-t 23:59:59', $start)); $results = array_filter($results, function($r) use ($start, $end) { $time = strtotime($r->time); return $time >= $start && $time <= $end; }); } // Filter by User $current_user = astr_safe_get('filter_user', 'text', '', 'manage_options', false); if ($current_user !== '') { $user_filter = astr_safe_get( 'filter_user' ); $results = array_filter($results, function($r) use ($user_filter) { return $r->user_name === $user_filter; }); } if (!empty($search_query)) { $results = array_filter($results, function($row) use ($search_query) { return stripos($row->plugin_name, $search_query) !== false; }); } $order_by = astr_safe_get('orderby', 'key', 'date', 'manage_options', false); $order = astr_safe_get('order', 'key', 'desc', 'manage_options', false); $order = in_array($order, ['asc','desc'], true) ? $order : 'asc'; $first_of_group = function($group) { return $group[0]; }; $grouped_history = []; if ($results) { foreach ($results as $row) { $plugin_path = $row->plugin_path; $grouped_history[$plugin_path][] = $row; } } foreach ($grouped_history as $plugin_path => $events) { $has_real_event = false; foreach ($events as $event) { if (!in_array($event->action, ['tracking_started','tracking_stopped'], true)) { $has_real_event = true; break; } } if (!$has_real_event) { unset($grouped_history[$plugin_path]); } } if ($order_by === 'name') { uasort($grouped_history, function($a, $b) use ($order, $first_of_group) { $a_name = $first_of_group($a)->plugin_name; $b_name = $first_of_group($b)->plugin_name; return $order === 'asc' ? strcasecmp($a_name, $b_name) : strcasecmp($b_name, $a_name); }); } elseif ($order_by === 'status') { uasort($grouped_history, function($a, $b) use ($order, $first_of_group) { $a_action = strtolower($first_of_group($a)->action); $b_action = strtolower($first_of_group($b)->action); return $order === 'asc' ? strcmp($a_action, $b_action) : strcmp($b_action, $a_action); }); } elseif ($order_by === 'date') { uasort($grouped_history, function($a, $b) use ($order) { $a_time = strtotime($a[0]->time); $b_time = strtotime($b[0]->time); return $order === 'asc' ? ($a_time <=> $b_time) : ($b_time <=> $a_time); }); } elseif ($order_by === 'user') { uasort($grouped_history, function($a, $b) use ($order, $first_of_group) { $a_user = strtolower($first_of_group($a)->user_name); $b_user = strtolower($first_of_group($b)->user_name); return $order === 'asc' ? strcmp($a_user, $b_user) : strcmp($b_user, $a_user); }); } $per_page = 10; $paged = max( 1, astr_safe_get( 'paged', 'absint', 1, 'manage_options', false ) ); $total = count($grouped_history); $total_pages = max( 1, (int) ceil( $total / $per_page ) ); $grouped_history = array_slice($grouped_history, ($paged - 1) * $per_page, $per_page, true); ?>

Plugins History

get_var( "SELECT COUNT(*) FROM (SELECT plugin_path FROM {$table} GROUP BY plugin_path HAVING SUM(action NOT IN ('tracking_started','tracking_stopped')) > 0) AS active_plugins" ); $base_url = admin_url( 'admin.php?page=astr-plugins-history' ); $all_plugins_link = add_query_arg( [], $base_url ); $link_class = 'astr-all-link' . ( $search_query ? ' active' : '' ); echo ''; echo 'All (' . intval( $all_plugins_total ) . ')'; echo ''; ?>
get_col( "SELECT DISTINCT DATE(time) as date_only FROM {$table_safe} ORDER BY date_only DESC" ); $months = []; foreach ($dates as $date) { $timestamp = strtotime($date); $month_key = gmdate('Y-m', $timestamp); $month_label = gmdate('F Y', $timestamp); $months[$month_key] = $month_label; } $current_month = astr_safe_get('filter_date', 'text', '', 'manage_options', false); if ( $current_month !== '' ) { $current_month = astr_safe_get('filter_date', 'text', '', 'manage_options', false); } ?>
= $per_page ) { astr_pagination( $total, $total_pages, $paged ); } ?>
$events_array) : ?> time) - strtotime($a->time); }); $last_event = $events_array[0]; $plugin_name = $last_event->plugin_name ?: $plugin_path; $all_plugins = get_plugins(); $is_installed = isset($all_plugins[$plugin_path]); $is_active = $is_installed && is_plugin_active($plugin_path); $paused_plugins = get_option( 'astr_paused_plugin_updates', array() ); $is_paused = isset( $paused_plugins[ $plugin_path ] ); $group_id = md5($plugin_path); $plugin_id = md5($plugin_path . $last_event->time); $has_multiple = count($events_array) > 1; $arrow_class = $has_multiple ? '' : ' astr-disabled'; ?> time ) ); $action = $event->action; $uname = $event->user_name; $ov = $event->old_version; $nv = $event->new_version; $plugin_id = md5( $plugin_path . $time ); $plugin_slug = dirname( $plugin_path ); $version_changelog = ''; if ( in_array( $action, array( 'updated', 'rolled_back' ), true ) && ! empty( $nv ) ) { $version_changelog = astr_get_plugin_version_changelog_safe( $plugin_path, $nv ); } ?>
action; $time = gmdate('d-m-Y H:i:s', strtotime($last_event->time)); $uname = $last_event->user_name; $ov = $last_event->old_version; $nv = $last_event->new_version; $version_changelog = ''; if ( in_array( $action, array( 'updated', 'rolled_back' ), true ) && ! empty( $nv ) ) { $version_changelog = astr_get_plugin_version_changelog_safe( $plugin_path, $nv ); } ?>
0 && strlen( $nv ) > 0 ) { $label = "Updated ({$ov} → {$nv})"; } if ( $action === 'rolled_back' && strlen( $ov ) > 0 && strlen( $nv ) > 0 ) { $label = "Reverted ({$ov} → {$nv})"; } if ($action === 'installed') { $label = 'Installed'; } echo esc_html($label); if ( ! empty( $version_changelog ) ) { echo ''; echo '
'; echo '
' . esc_html( $plugin_name ) . '
'; echo '
' . esc_html( $label ) . '
'; echo '
'; echo '
'; $changelog = astr_format_plugin_changelog( $version_changelog ); $changelog = str_replace( ''; } ?>
extra_info)) { echo ' '; $info = json_decode($last_event->extra_info, true); if (!is_array($info)) { $info = []; } if (is_array($info)) { echo '
'; echo '
' . esc_html($plugin_name) . '
'; echo '
' . esc_html(ucfirst($action)) . ' — ' . esc_html($time) . '
'; echo '
'; echo '
    '; if (!empty($info['user'])) echo '
  • OS User: ' . esc_html($info['user']) . '
  • '; if (!empty($info['uid'])) echo '
  • UID: ' . esc_html($info['uid']) . '
  • '; if (!empty($info['gid'])) echo '
  • GID: ' . esc_html($info['gid']) . '
  • '; if (!empty($info['ip'])) echo '
  • IP Address: ' . esc_html($info['ip']) . '
  • '; if (!empty($info['cwd'])) echo '
  • Working Directory: ' . esc_html($info['cwd']) . '
  • '; if (!empty($info['command'])) echo '
  • Command: ' . esc_html($info['command']) . '
  • '; if (!empty($info['cli_path'])) echo '
  • WP-CLI Path: ' . esc_html($info['cli_path']) . '
  • '; if (!empty($info['hostname'])) echo '
  • Hostname: ' . esc_html($info['hostname']) . '
  • '; if (!empty($info['sapi'])) echo '
  • SAPI: ' . esc_html($info['sapi']) . '
  • '; if (!empty($info['ssh_info'])) echo '
  • SSH Info: ' . esc_html($info['ssh_info']) . '
  • '; echo '
'; } } ?>
0 && strlen( $nv ) > 0 ) { $label = "Updated ({$ov} → {$nv})"; } if ( $action === 'rolled_back' && strlen( $ov ) > 0 && strlen( $nv ) > 0 ) { $label = "Reverted ({$ov} → {$nv})"; } echo esc_html( $label ); if ( ! empty( $version_changelog ) ) { echo ''; echo '
'; echo '
' . esc_html( $plugin_name ) . '
'; echo '
' . esc_html( $label ) . '
'; echo '
'; echo '
'; $changelog = astr_format_plugin_changelog( $version_changelog ); $changelog = str_replace( ''; } ?>
extra_info ) ) { echo ''; $info = json_decode( $event->extra_info, true ); if ( ! is_array( $info ) ) { $info = []; } if ( is_array( $info ) ) { echo '
'; echo '
' . esc_html( $plugin_name ) . '
'; echo '
' . esc_html( ucfirst( $action ) ) . ' — ' . esc_html( $time ) . '
'; echo '
'; echo '
    '; if ( ! empty( $info['user'] ) ) { echo '
  • OS User: ' . esc_html( $info['user'] ) . '
  • '; } if ( ! empty( $info['uid'] ) ) { echo '
  • UID: ' . esc_html( $info['uid'] ) . '
  • '; } if ( ! empty( $info['gid'] ) ) { echo '
  • GID: ' . esc_html( $info['gid'] ) . '
  • '; } if ( ! empty( $info['ip'] ) ) { echo '
  • IP Address: ' . esc_html( $info['ip'] ) . '
  • '; } if ( ! empty( $info['cwd'] ) ) { echo '
  • Working Directory: ' . esc_html( $info['cwd'] ) . '
  • '; } if ( ! empty( $info['command'] ) ) { echo '
  • Command: ' . esc_html( $info['command'] ) . '
  • '; } if ( ! empty( $info['cli_path'] ) ) { echo '
  • WP-CLI Path: ' . esc_html( $info['cli_path'] ) . '
  • '; } if ( ! empty( $info['hostname'] ) ) { echo '
  • Hostname: ' . esc_html( $info['hostname'] ) . '
  • '; } if ( ! empty( $info['sapi'] ) ) { echo '
  • SAPI: ' . esc_html( $info['sapi'] ) . '
  • '; } if ( ! empty( $info['ssh_info'] ) ) { echo '
  • SSH Info: ' . esc_html( $info['ssh_info'] ) . '
  • '; } echo '
'; } } ?>
= $per_page ) { astr_pagination( $total, $total_pages, $paged ); } ?>
×
response ) ) { return $transient; } $paused_plugins = get_option( 'astr_paused_plugin_updates', array() ); foreach ( $paused_plugins as $plugin => $value ) { if ( isset( $transient->response[ $plugin ] ) ) { unset( $transient->response[ $plugin ] ); } } return $transient; } /*Get the full changelog for a plugin.*/ function astr_get_plugin_changelog( $slug ) { if ( empty( $slug ) ) { return ''; } $cache_key = 'astr_changelog_' . md5( $slug ); $cached = get_transient( $cache_key ); if ( false !== $cached ) { return $cached; } require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; $plugin = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => true, ), ) ); if ( is_wp_error( $plugin ) ) { return ''; } if ( empty( $plugin->sections['changelog'] ) ) { return ''; } $changelog = wp_kses_post( $plugin->sections['changelog'] ); set_transient( $cache_key, $changelog, DAY_IN_SECONDS ); return $changelog; } /*Get the changelog section for a specific plugin version.*/ function astr_get_plugin_version_changelog( $slug, $version ) { $changelog = astr_get_plugin_changelog( $slug ); if ( empty( $changelog ) ) { return ''; } // Remove HTML. $text = wp_strip_all_tags( $changelog ); $text = preg_replace( "/\r\n|\r/", "\n", $text ); // Split into version sections. preg_match_all( '/^\s*=*\s*(\d+(?:\.\d+)+)(?:\s*=*)?(?:\s*[–-]\s*\d{4}-\d{2}-\d{2})?/m', $text, $matches, PREG_OFFSET_CAPTURE ); if ( empty( $matches[0] ) ) { return trim( $text ); } $sections = array(); foreach ( $matches[0] as $index => $match ) { $start = $match[1]; $end = isset( $matches[0][ $index + 1 ] ) ? $matches[0][ $index + 1 ][1] : strlen( $text ); $section = trim( substr( $text, $start, $end - $start ) ); $sections[] = array( 'header' => $matches[1][ $index ][0], 'body' => $section, ); } $exact_match = null; $patch_match = null; foreach ( $sections as $section ) { if ( preg_match( '/^' . preg_quote( $version, '/' ) . '(?=\D|$)/', $section['header'] ) ) { $exact_match = $section['body']; break; } if ( preg_match( '/^' . preg_quote( $version, '/' ) . '(?=\D|$)/', $section['header'] ) ) { if ( null === $patch_match ) { $patch_match = $section['body']; } } } if ( $exact_match !== null ) { return $exact_match; } if ( $patch_match !== null ) { return $patch_match; } return sprintf( 'Version %s is no longer available in the WordPress plugin repository. Only newer releases are currently published.', $version ); } // Get real WordPress.org plugin slug for changelog requests. function astr_get_plugin_api_slug( $plugin_path ) { $cache_key = 'astr_plugin_api_slug_' . md5( $plugin_path ); /*$cache_key = 'astr_plugin_api_slug_v2_' . md5( $plugin_path );*/ $cached = get_transient( $cache_key ); if ( false !== $cached ) { return $cached; } $slug = dirname( $plugin_path ); require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; $api = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => false, ), ) ); if ( ! is_wp_error( $api ) && ! empty( $api->slug ) ) { set_transient( $cache_key, $api->slug, DAY_IN_SECONDS ); return $api->slug; } set_transient( $cache_key, $slug, DAY_IN_SECONDS ); return $slug; } // Get plugin homepage from WordPress.org with caching. function astr_get_plugin_homepage( $plugin_slug ) { $cache_key = 'astr_plugin_homepage_' . md5( $plugin_slug ); $cached = get_transient( $cache_key ); if ( false !== $cached ) { return $cached; } if ( false !== $cached ) { return $cached; } require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; $api = plugins_api( 'plugin_information', array( 'slug' => $plugin_slug, 'fields' => array( 'homepage' => true, ), ) ); if ( ! is_wp_error( $api ) && ! empty( $api->homepage ) ) { set_transient( $cache_key, $api->homepage, DAY_IN_SECONDS ); return $api->homepage; } $fallback = 'https://wordpress.org/plugins/' . $plugin_slug . '/'; set_transient( $cache_key, $fallback, DAY_IN_SECONDS ); return $fallback; } // Get changelog for a specific plugin version using plugin path with WordPress.org slug fallback. function astr_get_plugin_version_changelog_safe( $plugin_path, $version ) { $plugin_slug = dirname( $plugin_path ); $changelog = astr_get_plugin_version_changelog( $plugin_slug, $version ); if ( ! empty( $changelog ) ) { return $changelog; } $api_slug = astr_get_plugin_api_slug( $plugin_path ); if ( $api_slug !== $plugin_slug ) { $changelog = astr_get_plugin_version_changelog( $api_slug, $version ); if ( ! empty( $changelog ) ) { return $changelog; } } return sprintf( 'Version %s is no longer available in the WordPress plugin repository. Only newer releases are currently published.', $version ); } // Format plugin changelog for modal output. function astr_format_plugin_changelog( $changelog ) { if ( empty( $changelog ) ) { return ''; } $changelog = make_clickable( esc_html( $changelog ) ); $lines = preg_split( '/\r\n|\r|\n/', $changelog ); $output = ''; $list_open = false; foreach ( $lines as $line ) { $line = trim( $line ); $line = html_entity_decode( $line, ENT_QUOTES | ENT_HTML5, 'UTF-8' ); if ( $line === '' ) { continue; } // Version. if ( preg_match( '/^\s*=*\s*\d+(?:\.\d+)+(?:\s*=*)?(?:\s*[—–-]\s*\d{4}-\d{2}-\d{2}|\s*\(\d{1,2}\s+[A-Za-z]+\s+\d{4}\)|\s*\(\d{4}[\/-]\d{2}[\/-]\d{2}\))?\s*$/u', $line ) || preg_match( '/^\d+(?:\.\d+)+\s*[—–-]?\s*\d{4}-\d{2}-\d{2}$/u', $line ) ) { if ( $list_open ) { $output .= ''; $list_open = false; } if ( preg_match( '/^(\d+(?:\.\d+)+)\s*[—–-]?\s*(\d{4}-\d{2}-\d{2})$/u', $line, $m ) ) { $output .= '

' . $m[1] . ' ' . $m[2] . '

'; } else { $clean = trim( $line, "= \t\n\r\0\x0B" ); if ( preg_match( '/^(\d+(?:\.\d+)+)\s*[–-]\s*(\d{4}-\d{2}-\d{2})$/u', $clean, $m ) ) { $output .= '

' . $m[1] . ' ' . $m[2] . '

'; } elseif ( preg_match( '/^(\d+(?:\.\d+)+)\s+\((\d{4}[\/-]\d{2}[\/-]\d{2}|.+)\)$/u', $clean, $m ) ) { $output .= '

' . $m[1] . ' (' . $m[2] . ')

'; } else { $output .= '

' . $clean . '

'; } } continue; } // Date. if ( preg_match( '/^(?:[A-Za-z]+\s+\d{1,2}(?:st|nd|rd|th)?,\s+\d{4}|\d{4}-\d{2}-\d{2})$/', $line ) ) { if ( $list_open ) { $output .= ''; $list_open = false; } $output .= '

' . $line . '

'; continue; } if ( ! $list_open ) { $output .= ''; } return $output; } // Get all available plugin versions from the WordPress.org SVN repository. function astr_get_plugin_versions( $slug ) { $cache_key = 'astr_versions_' . md5( $slug ); /*$cache_key = 'astr_versions_v2_' . md5( $slug );*/ $cached = get_transient( $cache_key ); if ( false !== $cached ) { return $cached; } $url = 'https://plugins.svn.wordpress.org/' . $slug . '/tags/'; $response = wp_remote_get( $url, array( 'timeout' => 20, ) ); if ( is_wp_error( $response ) ) { return array(); } $html = wp_remote_retrieve_body( $response ); preg_match_all( '#>([0-9]+(?:\.[0-9]+)+(?:-[^/]*)?)/<#', $html, $matches ); $versions = $matches[1]; $versions = array_filter( $versions, static function ( $version ) { return strpos( $version, '-' ) === false; } ); usort( $versions, 'version_compare' ); $versions = array_reverse( $versions ); $versions = array_slice( $versions, 0, 5 ); $versions = array_values( $versions ); set_transient( $cache_key, $versions, DAY_IN_SECONDS ); return $versions; } function astr_get_plugin_admin_url( $plugin_file ) { if ( ! function_exists( 'get_plugin_data' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } if ( basename( $plugin_file ) === 'hello.php' ) { return 'https://wordpress.org/plugins/hello-dolly/'; } $plugin_path = WP_PLUGIN_DIR . '/' . $plugin_file; if ( ! file_exists( $plugin_path ) ) { return ''; } $plugin_data = get_plugin_data( $plugin_path, false, false ); // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound $action_links = apply_filters( 'plugin_action_links_' . $plugin_file, array(), $plugin_file, $plugin_data, '' ); // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound if ( empty( $action_links ) ) { // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound $action_links = apply_filters( 'plugin_action_links', array(), $plugin_file, $plugin_data, '' ); // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound } foreach ( $action_links as $link ) { if ( stripos( $link, '>Settings<' ) !== false || stripos( $link, '>Настройки<' ) !== false ) { if ( preg_match( '/href=["\']([^"\']+)["\']/', $link, $matches ) ) { return html_entity_decode( $matches[1] ); } } } return ''; } function astr_find_plugin_admin_page_by_menu( $plugin_file ) { global $menu, $submenu; if ( ! function_exists( 'get_plugin_data' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $plugin_path = WP_PLUGIN_DIR . '/' . $plugin_file; if ( ! file_exists( $plugin_path ) ) { return ''; } $plugin_data = get_plugin_data( $plugin_path, false, false ); if ( empty( $plugin_data['Name'] ) ) { return ''; } $plugin_name = trim( wp_strip_all_tags( $plugin_data['Name'] ) ); global $_registered_pages, $_parent_pages; $plugin_slug = dirname( $plugin_file ); if ( 'custom-post-type-ui' === $plugin_slug && isset( $submenu['cptui_main_menu'][1][2] ) ) { return admin_url( 'admin.php?page=' . $submenu['cptui_main_menu'][1][2] ); } if ( 'cmp-coming-soon-maintenance' === $plugin_slug ) { return admin_url( 'admin.php?page=cmp-settings' ); } //Dynamically detect plugin settings inside a registered parent admin page. if ( 0 === strpos( strtolower( $plugin_slug ), 'salient' ) ) { if ( 'salient-core' === $plugin_slug ) { return admin_url( 'admin.php?page=SalientChildTheme&tab=1' ); } if ( 'salient-custom-branding' === $plugin_slug ) { return admin_url( 'admin.php?page=salient-custom-branding' ); } $plugin_words = preg_split( '/[-_]+/', strtolower( dirname( $plugin_file ) ) ); $plugin_words = array_filter( $plugin_words, function ( $word ) { return strlen( $word ) >= 5; } ); if ( ! empty( $plugin_words ) && ! empty( $submenu ) && ! empty( $_parent_pages ) ) { foreach ( $submenu as $parent_slug => $items ) { if ( empty( $items ) || ! is_array( $items ) ) { continue; } $parent_is_registered = false; foreach ( array_keys( $_registered_pages ) as $hook ) { if ( false !== strpos( $hook, 'page_' . $parent_slug ) ) { $parent_is_registered = true; break; } } if ( ! $parent_is_registered ) { continue; } foreach ( $items as $item ) { if ( empty( $item[0] ) || empty( $item[2] ) ) { continue; } $title = trim( wp_strip_all_tags( $item[0] ) ); $slug = (string) $item[2]; if ( false !== strpos( $slug, '.php' ) && false === strpos( $slug, 'admin.php' ) ) { continue; } $title_lower = strtolower( $title ); foreach ( $plugin_words as $word ) { if ( false === strpos( $title_lower, $word ) ) { continue; } if ( filter_var( $slug, FILTER_VALIDATE_URL ) ) { return $slug; } return admin_url( 'admin.php?page=' . $slug ); } } } } } if ( ! empty( $_registered_pages ) && is_array( $_registered_pages ) ) { foreach ( array_keys( $_registered_pages ) as $hook ) { if ( stripos( $hook, $plugin_slug ) !== false ) { if ( preg_match( '/page_(.+)$/', $hook, $m ) ) { $slug = $m[1]; if ( isset( $_parent_pages[ $slug ] ) ) { $parent = $_parent_pages[ $slug ]; if ( filter_var( $slug, FILTER_VALIDATE_URL ) ) { return $slug; } if ( empty( $parent ) ) { return admin_url( 'admin.php?page=' . $slug ); } if ( strpos( $parent, '.php' ) !== false ) { return admin_url( $parent . '?page=' . $slug ); } return admin_url( 'admin.php?page=' . $slug ); } } } } } foreach ( (array) $menu as $item ) { if ( empty( $item[0] ) || empty( $item[2] ) ) { continue; } $menu_name = trim( wp_strip_all_tags( $item[0] ) ); if ( 0 === strcasecmp( $menu_name, $plugin_name ) ) { $slug = (string) $item[2]; if ( filter_var( $slug, FILTER_VALIDATE_URL ) ) { return $slug; } if ( false !== strpos( $slug, '.php' ) ) { return admin_url( $slug ); } return admin_url( 'admin.php?page=' . $slug ); } } foreach ( (array) $submenu as $parent => $items ) { foreach ( $items as $item ) { if ( empty( $item[0] ) || empty( $item[2] ) ) { continue; } $menu_name = trim( wp_strip_all_tags( $item[0] ) ); if ( 0 === strcasecmp( $menu_name, $plugin_name ) ) { $slug = (string) $item[2]; if ( false !== strpos( $parent, '.php' ) ) { return admin_url( $parent . '?page=' . $slug ); } return admin_url( 'admin.php?page=' . $slug ); } } } foreach ( (array) $menu as $item ) { if ( empty( $item[3] ) || empty( $item[2] ) ) { continue; } if ( 0 !== strcasecmp( trim( wp_strip_all_tags( $item[3] ) ), $plugin_name ) ) { continue; } $slug = (string) $item[2]; if ( filter_var( $slug, FILTER_VALIDATE_URL ) ) { return $slug; } if ( false !== strpos( $slug, '.php' ) ) { return admin_url( $slug ); } return admin_url( 'admin.php?page=' . $slug ); } foreach ( (array) $submenu as $items ) { foreach ( $items as $item ) { if ( empty( $item[3] ) || empty( $item[2] ) ) { continue; } if ( 0 !== strcasecmp( trim( wp_strip_all_tags( $item[3] ) ), $plugin_name ) ) { continue; } $slug = (string) $item[2]; if ( filter_var( $slug, FILTER_VALIDATE_URL ) ) { return $slug; } if ( false !== strpos( $slug, '.php' ) ) { return admin_url( $slug ); } return admin_url( 'admin.php?page=' . $slug ); } } if ( 'advanced-custom-fields' === dirname( $plugin_file ) ) { if ( is_plugin_active( $plugin_file ) ) { return admin_url( 'edit.php?post_type=acf-field-group' ); } return ! empty( $plugin_data['PluginURI'] ) ? $plugin_data['PluginURI'] : ''; } return ''; }