plugin_dir = get_template_directory() . '/libs/plugin-recommend';
$this->plugin_url = get_template_directory_uri() . '/libs/plugin-recommend';
// Reset old notice dismissals only once (for migration to new system)
$this->migrate_notice_dismissal();
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
add_action('wp_ajax_shop_toolkit_install_plugin', array($this, 'ajax_install_plugin'));
add_action('wp_ajax_shop_toolkit_activate_plugin', array($this, 'ajax_activate_plugin'));
add_action('wp_ajax_shop_toolkit_update_plugin', array($this, 'ajax_update_plugin'));
add_action('wp_ajax_shop_toolkit_dismiss_plugin_notice', array($this, 'ajax_dismiss_plugin_notice'));
add_action('wp_ajax_shop_toolkit_dismiss_update_notice', array($this, 'ajax_dismiss_update_notice'));
add_action('wp_ajax_shop_toolkit_dismiss_install_notice', array($this, 'ajax_dismiss_install_notice'));
add_action('wp_ajax_shop_toolkit_update_all_plugins', array($this, 'ajax_update_all_plugins'));
add_action('wp_ajax_shop_toolkit_install_required_plugins', array($this, 'ajax_install_required_plugins'));
add_action('wp_ajax_shop_toolkit_install_recommended_plugins', array($this, 'ajax_install_recommended_plugins'));
add_action('wp_ajax_shop_toolkit_check_recommended_plugins_status', array($this, 'ajax_check_recommended_plugins_status'));
add_action('wp_ajax_shop_toolkit_check_recommended_plugins_status', array($this, 'ajax_check_recommended_plugins_status'));
add_action('admin_notices', array($this, 'show_recommendation_notice'));
add_action('admin_notices', array($this, 'show_update_notice'));
// Auto-install required plugins
add_action('after_switch_theme', array($this, 'auto_install_required_plugins'));
add_action('admin_init', array($this, 'check_required_plugins'));
}
/**
* Add admin menu page
*/
public function add_admin_menu() {
add_theme_page(
__('Recommended Plugins', 'asthir'),
__('Recommended Plugins', 'asthir'),
'manage_options',
'shop-toolkit-plugins',
array($this, 'render_admin_page')
);
}
/**
* Get recommended plugins (including local plugins)
*/
public function get_recommended_plugins() {
return array(
// WordPress.org plugins
'magical-addons-for-elementor' => array(
'name' => __('Magical Addons', 'asthir'),
'slug' => 'magical-addons-for-elementor',
'file' => 'magical-addons-for-elementor/magical-addons-for-elementor.php',
'description' => __('Enhance your site with a collection of magical addons for Elementor.', 'asthir'),
'category' => 'Essential',
'required' => false,
'featured' => false,
'is_local' => false
),
'magical-products-display' => array(
'name' => __('Magical Product Display', 'asthir'),
'slug' => 'magical-products-display',
'file' => 'magical-products-display/magical-products-display.php',
'description' => __('Display your Product in a magical way with this addon for Elementor.', 'asthir'),
'category' => 'Essential',
'required' => false,
'featured' => true,
'is_local' => false
),
'magical-posts-display' => array(
'name' => __('Magical Posts Display', 'asthir'),
'slug' => 'magical-posts-display',
'file' => 'magical-posts-display/magical-posts-display.php',
'description' => __('Display your posts in a magical way with this addon for Elementor.', 'asthir'),
'category' => 'Essential',
'required' => false,
'featured' => true,
'is_local' => false
),
'elementor' => array(
'name' => __('Elementor Page Builder', 'asthir'),
'slug' => 'elementor',
'file' => 'elementor/elementor.php',
'description' => __('Create beautiful pages with drag & drop page builder. Perfect for creating stunning layouts with your theme.', 'asthir'),
'category' => 'Page Builder',
'required' => false,
'featured' => true,
'is_local' => false
),
'click-to-top' => array(
'name' => __('Click to Top', 'asthir'),
'slug' => 'click-to-top',
'file' => 'click-to-top/click-to-top.php',
'description' => __('Add a "click to top" button to your site.', 'asthir'),
'category' => 'Utility',
'required' => false,
'featured' => false,
'is_local' => false
),
'wp-edit-password-protected' => array(
'name' => __('WP Edit Password Protected', 'asthir'),
'slug' => 'wp-edit-password-protected',
'file' => 'wp-edit-password-protected/wp-edit-password-protected.php',
'description' => __('Easily manage password protection for your WordPress content.', 'asthir'),
'category' => 'Security',
'required' => false,
'featured' => true,
'is_local' => false
),
'easy-share-solution' => array(
'name' => __('Easy Share Solution', 'asthir'),
'slug' => 'easy-share-solution',
'file' => 'easy-share-solution/easy-share-solution.php',
'description' => __('Easily add social sharing buttons to your content.', 'asthir'),
'category' => 'Utility',
'required' => false,
'featured' => true,
'is_local' => false
),
'magical-blocks' => array(
'name' => __('Magical Blocks', 'asthir'),
'slug' => 'magical-blocks',
'file' => 'magical-blocks/magical-blocks.php',
'description' => __('Add magical blocks to your content.', 'asthir'),
'category' => 'Utility',
'required' => false,
'featured' => false,
'is_local' => false
),
'woocommerce' => array(
'name' => __('WooCommerce', 'asthir'),
'slug' => 'woocommerce',
'file' => 'woocommerce/woocommerce.php',
'description' => __('Add woocommerce to your website.', 'asthir'),
'category' => 'Utility',
'required' => false,
'featured' => false,
'is_local' => false
),
);
}
/**
* Check plugin status including version checking for updates
*/
public function get_plugin_status($plugin) {
$this->check_plugin_functions();
$plugin_file = $plugin['file'];
if (is_plugin_active($plugin_file)) {
// Check if plugin needs update (for plugins with version specified)
if (isset($plugin['version']) && !empty($plugin['version'])) {
$current_version = $this->get_plugin_version($plugin_file);
if ($current_version && version_compare($current_version, $plugin['version'], '<')) {
return 'needs-update';
}
}
return 'active';
} elseif (file_exists(WP_PLUGIN_DIR . '/' . $plugin_file)) {
// Check if inactive plugin needs update
if (isset($plugin['version']) && !empty($plugin['version'])) {
$current_version = $this->get_plugin_version($plugin_file);
if ($current_version && version_compare($current_version, $plugin['version'], '<')) {
return 'inactive-needs-update';
}
}
return 'inactive';
} else {
return 'not-installed';
}
}
/**
* Get plugin version from plugin header
*/
private function get_plugin_version($plugin_file) {
$plugin_path = WP_PLUGIN_DIR . '/' . $plugin_file;
if (!file_exists($plugin_path)) {
return false;
}
// Get plugin data
if (!function_exists('get_plugin_data')) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$plugin_data = get_plugin_data($plugin_path);
return isset($plugin_data['Version']) ? $plugin_data['Version'] : false;
}
/**
* Check if plugin is a local plugin
*/
private function is_local_plugin($plugin) {
return isset($plugin['is_local']) && $plugin['is_local'] === true;
}
/**
* Render admin page
*/
public function render_admin_page() {
$plugins = $this->get_recommended_plugins();
?>
is_local_plugin($plugin);
$current_version = '';
$required_version = isset($plugin['version']) ? $plugin['version'] : '';
if ($status === 'active' || $status === 'inactive' || $status === 'needs-update' || $status === 'inactive-needs-update') {
$current_version = $this->get_plugin_version($plugin['file']);
}
switch ($status) {
case 'active':
echo '' . esc_html__('Active', 'asthir') . '';
break;
case 'needs-update':
echo '';
break;
case 'inactive':
echo '';
break;
case 'inactive-needs-update':
echo '';
break;
case 'not-installed':
if ($is_local) {
echo '';
} else {
echo '';
}
break;
}
// Show version info if available
if ($current_version && $required_version) {
echo '';
printf(esc_html__('Current: %s | Required: %s', 'asthir'), $current_version, $required_version);
echo '';
} elseif ($current_version) {
echo '';
printf(esc_html__('Version: %s', 'asthir'), $current_version);
echo '';
} elseif ($required_version) {
echo '';
printf(esc_html__('Required Version: %s', 'asthir'), $required_version);
echo '';
}
}
/**
* Get status text
*/
private function get_status_text($status) {
switch ($status) {
case 'active':
return __('Active', 'asthir');
case 'needs-update':
return __('Update Available', 'asthir');
case 'inactive':
return __('Installed but not active', 'asthir');
case 'inactive-needs-update':
return __('Update Available (Inactive)', 'asthir');
case 'not-installed':
return __('Not installed', 'asthir');
default:
return __('Unknown', 'asthir');
}
}
/**
* Show update notice for plugins that need updates
*/
public function show_update_notice() {
$screen = get_current_screen();
// Only show on dashboard, themes, and plugins pages
if (!in_array($screen->id, array('dashboard', 'themes', 'plugins', 'appearance_page_shop-toolkit-plugins'))) {
return;
}
// Check if user dismissed the update notice
$dismissed_time = get_user_meta(get_current_user_id(), 'shop_toolkit_hide_update_notice_time', true);
$show_update_notice = !$dismissed_time || (time() - $dismissed_time) >= (7 * 24 * 60 * 60); // 7 days
if (!$show_update_notice) {
return;
}
// Get plugins that need updates
$plugins_need_update = $this->get_plugins_needing_updates();
if (empty($plugins_need_update)) {
return;
}
?>
get_recommended_plugins();
$plugins_need_update = array();
foreach ($all_plugins as $slug => $plugin) {
$status = $this->get_plugin_status($plugin);
if (in_array($status, array('needs-update', 'inactive-needs-update'))) {
$plugins_need_update[$slug] = $plugin;
}
}
return $plugins_need_update;
}
/**
* AJAX handler for dismissing update notice
*/
public function ajax_dismiss_update_notice() {
check_ajax_referer('shop_toolkit_plugins_nonce', 'nonce');
// Save the current timestamp when update notice is dismissed
update_user_meta(get_current_user_id(), 'shop_toolkit_hide_update_notice_time', time());
wp_send_json_success();
}
/**
* AJAX handler for dismissing install notice
*/
public function ajax_dismiss_install_notice() {
check_ajax_referer('shop_toolkit_plugins_nonce', 'nonce');
// Save the current timestamp when install notice is dismissed
update_user_meta(get_current_user_id(), 'shop_toolkit_hide_install_notice_time', time());
wp_send_json_success();
}
/**
* AJAX handler for dismissing plugin notice
*/
public function ajax_dismiss_plugin_notice() {
check_ajax_referer('shop_toolkit_plugins_nonce', 'nonce');
$notice_type = sanitize_text_field($_POST['notice_type']);
if ($notice_type === 'recommended') {
// Save the current timestamp when recommended notice is dismissed
update_user_meta(get_current_user_id(), 'shop_toolkit_hide_recommended_notice_time9', time());
}
wp_send_json_success();
}
/**
* AJAX handler for updating all plugins
*/
public function ajax_update_all_plugins() {
check_ajax_referer('shop_toolkit_plugins_nonce', 'nonce');
if (!current_user_can('update_plugins')) {
wp_die(__('You do not have permission to update plugins.', 'asthir'));
}
$plugins_need_update = $this->get_plugins_needing_updates();
$results = array();
$success_count = 0;
$total_count = count($plugins_need_update);
foreach ($plugins_need_update as $slug => $plugin) {
$is_local = $this->is_local_plugin($plugin);
if ($is_local) {
$result = $this->update_local_plugin($plugin);
} else {
$result = $this->update_wordpress_org_plugin($plugin['file']);
}
if ($result) {
$results[$slug] = 'updated';
$success_count++;
} else {
$results[$slug] = 'failed';
}
}
if ($success_count === $total_count) {
wp_send_json_success(array(
'message' => sprintf(__('%d plugins updated successfully.', 'asthir'), $success_count),
'results' => $results
));
} else {
wp_send_json_error(array(
'message' => sprintf(__('%d of %d plugins updated successfully.', 'asthir'), $success_count, $total_count),
'results' => $results
));
}
}
/**
* Enqueue admin scripts and styles
*/
public function enqueue_admin_scripts($hook) {
// Load scripts on plugin page, dashboard, themes page, and plugins page
if (!in_array($hook, array('appearance_page_shop-toolkit-plugins', 'index.php', 'themes.php', 'plugins.php'))) {
return;
}
wp_enqueue_script(
'shop-toolkit-plugins-admin',
$this->plugin_url . '/assets/js/admin-plugins.js',
array('jquery'),
ASTHIR_VERSION,
true
);
wp_localize_script('shop-toolkit-plugins-admin', 'blogBuildProPlugins', array(
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('shop_toolkit_plugins_nonce'),
'strings' => array(
'installing' => __('Installing...', 'asthir'),
'activating' => __('Activating...', 'asthir'),
'updating' => __('Updating...', 'asthir'),
'installed' => __('Installed', 'asthir'),
'activated' => __('Activated', 'asthir'),
'updated' => __('Updated', 'asthir'),
'active' => __('Active', 'asthir'),
'inactive' => __('Inactive', 'asthir'),
'notInstalled' => __('Not Installed', 'asthir'),
'needsUpdate' => __('Update Available', 'asthir'),
'inactiveNeedsUpdate' => __('Update Available (Inactive)', 'asthir'),
'install' => __('Install', 'asthir'),
'activate' => __('Activate', 'asthir'),
'update' => __('Update', 'asthir'),
'error' => __('Error occurred', 'asthir'),
)
));
wp_enqueue_style(
'shop-toolkit-plugins-admin',
$this->plugin_url . '/assets/css/admin-plugins.css',
array(),
ASTHIR_VERSION
);
}
/**
* AJAX handler for plugin installation
*/
public function ajax_install_plugin() {
check_ajax_referer('shop_toolkit_plugins_nonce', 'nonce');
if (!current_user_can('install_plugins')) {
wp_die(__('You do not have permission to install plugins.', 'asthir'));
}
$slug = sanitize_text_field($_POST['slug']);
$is_local = isset($_POST['is_local']) && $_POST['is_local'] === '1';
error_log('Shop Toolkit Pro: Installing plugin - Slug: ' . $slug . ', Is Local: ' . ($is_local ? 'Yes' : 'No'));
if ($is_local) {
// Handle local plugin installation
$plugins = $this->get_recommended_plugins();
if (!isset($plugins[$slug])) {
error_log('Shop Toolkit Pro: Plugin not found in recommendations: ' . $slug);
wp_send_json_error(__('Plugin not found in recommendations.', 'asthir'));
}
$plugin = $plugins[$slug];
error_log('Shop Toolkit Pro: Plugin config: ' . print_r($plugin, true));
// Check if source file exists
if (!isset($plugin['source']) || !file_exists($plugin['source'])) {
error_log('Shop Toolkit Pro: Source file check failed - Source: ' . (isset($plugin['source']) ? $plugin['source'] : 'not set') . ', Exists: ' . (isset($plugin['source']) && file_exists($plugin['source']) ? 'Yes' : 'No'));
wp_send_json_error(__('Local plugin zip file not found. Please ensure the plugin zip file exists in the theme directory.', 'asthir'));
}
// Check if ZipArchive is available
if (!class_exists('ZipArchive')) {
error_log('Shop Toolkit Pro: ZipArchive class not available');
wp_send_json_error(__('ZipArchive PHP extension is required for local plugin installation but not available on this server.', 'asthir'));
}
// Check if plugins directory is writable
if (!is_writable(WP_PLUGIN_DIR)) {
error_log('Shop Toolkit Pro: Plugin directory not writable: ' . WP_PLUGIN_DIR);
wp_send_json_error(__('Plugins directory is not writable. Please check directory permissions.', 'asthir'));
}
error_log('Shop Toolkit Pro: Attempting to install local plugin...');
$result = $this->install_local_plugin($plugin);
if ($result) {
error_log('Shop Toolkit Pro: Local plugin installation successful');
wp_send_json_success(__('Local plugin installed successfully.', 'asthir'));
} else {
error_log('Shop Toolkit Pro: Local plugin installation failed');
wp_send_json_error(__('Local plugin installation failed. Please check error logs for details.', 'asthir'));
}
} else {
// Handle WordPress.org plugin installation
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
$api = plugins_api('plugin_information', array('slug' => $slug));
if (is_wp_error($api)) {
wp_send_json_error(__('Plugin information could not be retrieved.', 'asthir'));
}
$upgrader = new Plugin_Upgrader(new WP_Ajax_Upgrader_Skin());
$install = $upgrader->install($api->download_link);
if ($install) {
wp_send_json_success(__('Plugin installed successfully.', 'asthir'));
} else {
wp_send_json_error(__('Plugin installation failed.', 'asthir'));
}
}
}
/**
* AJAX handler for plugin activation
*/
public function ajax_activate_plugin() {
check_ajax_referer('shop_toolkit_plugins_nonce', 'nonce');
if (!current_user_can('activate_plugins')) {
wp_die(__('You do not have permission to activate plugins.', 'asthir'));
}
$plugin_file = sanitize_text_field($_POST['file']);
$result = activate_plugin($plugin_file);
if (is_wp_error($result)) {
wp_send_json_error($result->get_error_message());
} else {
wp_send_json_success(__('Plugin activated successfully.', 'asthir'));
}
}
/**
* AJAX handler for plugin updates
*/
public function ajax_update_plugin() {
check_ajax_referer('shop_toolkit_plugins_nonce', 'nonce');
if (!current_user_can('update_plugins')) {
wp_die(__('You do not have permission to update plugins.', 'asthir'));
}
$slug = sanitize_text_field($_POST['slug']);
$plugin_file = sanitize_text_field($_POST['file']);
$is_local = isset($_POST['is_local']) && $_POST['is_local'] === '1';
$plugins = $this->get_recommended_plugins();
if (!isset($plugins[$slug])) {
wp_send_json_error(__('Plugin not found.', 'asthir'));
}
$plugin = $plugins[$slug];
// Handle local plugin update
if ($is_local) {
$result = $this->update_local_plugin($plugin);
if ($result) {
wp_send_json_success(__('Local plugin updated successfully.', 'asthir'));
} else {
wp_send_json_error(__('Failed to update local plugin.', 'asthir'));
}
} else {
// Handle WordPress.org plugin update
$result = $this->update_wordpress_org_plugin($plugin_file);
if ($result) {
wp_send_json_success(__('Plugin updated successfully.', 'asthir'));
} else {
wp_send_json_error(__('Failed to update plugin.', 'asthir'));
}
}
}
/**
* AJAX handler for bulk installing required plugins
*/
public function ajax_install_required_plugins() {
check_ajax_referer('shop_toolkit_plugins_nonce', 'nonce');
if (!current_user_can('install_plugins')) {
wp_die(__('You do not have permission to install plugins.', 'asthir'));
}
$required_plugins = $this->get_required_plugins();
$results = array();
$success_count = 0;
$total_count = count($required_plugins);
foreach ($required_plugins as $slug => $plugin) {
$status = $this->get_plugin_status($plugin);
if ($status === 'active') {
$results[$slug] = 'already-active';
$success_count++;
} else {
$installed = $this->install_and_activate_plugin($plugin);
if ($installed) {
$results[$slug] = 'installed-and-activated';
$success_count++;
} else {
$results[$slug] = 'failed';
}
}
}
if ($success_count === $total_count) {
wp_send_json_success(array(
'message' => sprintf(__('%d required plugins installed and activated successfully.', 'asthir'), $success_count),
'results' => $results
));
} else {
wp_send_json_error(array(
'message' => sprintf(__('%d of %d required plugins installed successfully.', 'asthir'), $success_count, $total_count),
'results' => $results
));
}
}
/**
* AJAX handler for bulk installing recommended plugins
*/
public function ajax_install_recommended_plugins() {
check_ajax_referer('shop_toolkit_plugins_nonce', 'nonce');
if (!current_user_can('install_plugins')) {
wp_die(__('You do not have permission to install plugins.', 'asthir'));
}
$recommended_plugins = $this->get_recommended_plugins();
$results = array();
$success_count = 0;
$total_count = count($recommended_plugins);
foreach ($recommended_plugins as $slug => $plugin) {
$status = $this->get_plugin_status($plugin);
if ($status === 'active') {
$results[$slug] = 'already-active';
$success_count++;
} else {
$installed = $this->install_and_activate_plugin($plugin);
if ($installed) {
$results[$slug] = 'installed-and-activated';
$success_count++;
} else {
$results[$slug] = 'failed';
}
}
}
if ($success_count === $total_count) {
wp_send_json_success(array(
'message' => sprintf(__('%d recommended plugins installed and activated successfully.', 'asthir'), $success_count),
'results' => $results
));
} else {
wp_send_json_error(array(
'message' => sprintf(__('%d of %d recommended plugins installed successfully.', 'asthir'), $success_count, $total_count),
'results' => $results
));
}
}
/**
* AJAX handler to check if all recommended plugins are active
*/
public function ajax_check_recommended_plugins_status() {
check_ajax_referer('shop_toolkit_plugins_nonce', 'nonce');
$all_active = $this->are_all_recommended_plugins_active();
wp_send_json_success(array(
'all_active' => $all_active,
'message' => $all_active ? __('All recommended plugins are active!', 'asthir') : __('Some recommended plugins are not active.', 'asthir')
));
}
/**
* Show recommendation notice in admin
*/
public function show_recommendation_notice() {
$screen = get_current_screen();
// Only show on dashboard, themes, and plugins pages
if (!in_array($screen->id, array('dashboard', 'themes', 'plugins', 'appearance_page_shop-toolkit-plugins'))) {
return;
}
// Check if there are any missing required plugins
$missing_required = array();
$required_plugins = $this->get_required_plugins();
foreach ($required_plugins as $slug => $plugin) {
if ($this->get_plugin_status($plugin) !== 'active') {
$missing_required[$slug] = $plugin;
}
}
// Show REQUIRED plugins notice (non-dismissible) only if there are missing plugins
if (!empty($missing_required)) {
?>
id, array('dashboard', 'themes', 'plugins'))) {
$this->show_recommended_plugins_notice();
}
}
/**
* Show recommended plugins notice (dismissible)
*/
private function show_recommended_plugins_notice() {
// Check if user dismissed the recommended plugins notice
$dismissed_time = get_user_meta(get_current_user_id(), 'shop_toolkit_hide_recommended_notice_time9', true);
$show_recommended_notice = !$dismissed_time || (time() - $dismissed_time) >= (30 * 24 * 60 * 60); // 30 days
if (!$show_recommended_notice) {
return;
}
// Check if all recommended plugins are active
if ($this->are_all_recommended_plugins_active()) {
return;
}
// Get recommended plugins that are not active
$recommended_plugins = $this->get_recommended_plugins();
$inactive_recommended = array();
foreach ($recommended_plugins as $slug => $plugin) {
if (!$plugin['required'] && $this->get_plugin_status($plugin) !== 'active') {
$inactive_recommended[$slug] = $plugin;
}
}
if (empty($inactive_recommended)) {
return;
}
?>
get_required_plugins();
if (empty($required_plugins)) {
return;
}
// Set a flag to indicate we've processed theme activation
set_transient('shop_toolkit_theme_activated', true, 30);
// Install and activate required plugins
foreach ($required_plugins as $plugin) {
$this->install_and_activate_plugin($plugin);
}
// Set a notice that plugins were installed
set_transient('shop_toolkit_plugins_installed', true, 300);
}
/**
* Check for required plugins on admin init
*/
public function check_required_plugins() {
// Only check if user can install plugins
if (!current_user_can('install_plugins')) {
return;
}
// Only check once per session to avoid performance issues
if (get_transient('shop_toolkit_plugins_checked')) {
return;
}
// Set transient to avoid repeated checks
set_transient('shop_toolkit_plugins_checked', true, 3600); // 1 hour
// Get required plugins
$required_plugins = $this->get_required_plugins();
if (empty($required_plugins)) {
return;
}
// Check each required plugin
foreach ($required_plugins as $plugin) {
$status = $this->get_plugin_status($plugin);
if ($status === 'not-installed') {
$this->install_and_activate_plugin($plugin);
} elseif ($status === 'inactive') {
$this->activate_plugin_silent($plugin);
}
}
}
/**
* Get only required plugins
*/
private function get_required_plugins() {
$all_plugins = $this->get_recommended_plugins();
$required_plugins = array();
foreach ($all_plugins as $slug => $plugin) {
if (isset($plugin['required']) && $plugin['required'] === true) {
$required_plugins[$slug] = $plugin;
}
}
return $required_plugins;
}
/**
* Install and activate a plugin silently
*/
private function install_and_activate_plugin($plugin) {
// Check if plugin is already active
if ($this->get_plugin_status($plugin) === 'active') {
return true;
}
// Install plugin if not installed
if ($this->get_plugin_status($plugin) === 'not-installed') {
$installed = $this->install_plugin_silent($plugin);
if (!$installed) {
return false;
}
}
// Activate plugin
return $this->activate_plugin_silent($plugin);
}
/**
* Install plugin silently
*/
private function install_plugin_silent($plugin) {
try {
// Load the silent upgrader skin class
shop_toolkit_load_silent_upgrader_skin();
// Handle local plugin installation
if ($this->is_local_plugin($plugin)) {
return $this->install_local_plugin($plugin);
}
// Handle WordPress.org plugin installation
return $this->install_wordpress_org_plugin($plugin);
} catch (Exception $e) {
return false;
}
}
/**
* Install local plugin from zip file
*/
private function install_local_plugin($plugin) {
error_log('Shop Toolkit Pro: Starting local plugin installation for: ' . $plugin['name']);
// Basic checks
if (!isset($plugin['source']) || !file_exists($plugin['source'])) {
error_log('Shop Toolkit Pro: Source file missing: ' . (isset($plugin['source']) ? $plugin['source'] : 'not set'));
return false;
}
if (!class_exists('ZipArchive')) {
error_log('Shop Toolkit Pro: ZipArchive not available');
return false;
}
if (!is_writable(WP_PLUGIN_DIR)) {
error_log('Shop Toolkit Pro: Plugin directory not writable: ' . WP_PLUGIN_DIR);
return false;
}
$plugin_file_path = WP_PLUGIN_DIR . '/' . $plugin['file'];
if (file_exists($plugin_file_path)) {
error_log('Shop Toolkit Pro: Plugin already exists: ' . $plugin_file_path);
return true;
}
error_log('Shop Toolkit Pro: Source file: ' . $plugin['source'] . ' (size: ' . filesize($plugin['source']) . ')');
// Use a simple direct extraction approach
$zip = new ZipArchive();
$open_result = $zip->open($plugin['source']);
if ($open_result !== TRUE) {
error_log('Shop Toolkit Pro: Cannot open zip file. Error: ' . $open_result);
return false;
}
error_log('Shop Toolkit Pro: Zip opened. Files: ' . $zip->numFiles);
// Log first few files to debug structure
for ($i = 0; $i < min(3, $zip->numFiles); $i++) {
$file_info = $zip->statIndex($i);
error_log('Shop Toolkit Pro: File[' . $i . ']: ' . $file_info['name']);
}
// Extract directly to plugins directory
$extract_result = $zip->extractTo(WP_PLUGIN_DIR);
$zip->close();
if (!$extract_result) {
error_log('Shop Toolkit Pro: Extraction failed');
return false;
}
error_log('Shop Toolkit Pro: Extraction successful');
// Check if the expected plugin file now exists
if (file_exists($plugin_file_path)) {
error_log('Shop Toolkit Pro: Plugin file found: ' . $plugin_file_path);
return true;
}
// If not found, try to locate it
error_log('Shop Toolkit Pro: Expected plugin file not found: ' . $plugin_file_path);
// Look for any aakpro related directories
$plugin_dirs = glob(WP_PLUGIN_DIR . '/aakpro*', GLOB_ONLYDIR);
if (!empty($plugin_dirs)) {
foreach ($plugin_dirs as $dir) {
error_log('Shop Toolkit Pro: Found directory: ' . basename($dir));
$files = glob($dir . '/*.php');
foreach ($files as $file) {
error_log('Shop Toolkit Pro: Found PHP file: ' . basename($file));
}
}
}
return false;
}
/**
* Install WordPress.org plugin
*/
private function install_wordpress_org_plugin($plugin) {
try {
include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
// Get plugin info from WordPress.org
$api = plugins_api('plugin_information', array(
'slug' => $plugin['slug'],
'fields' => array(
'short_description' => false,
'sections' => false,
'requires' => false,
'rating' => false,
'ratings' => false,
'downloaded' => false,
'last_updated' => false,
'added' => false,
'tags' => false,
'compatibility' => false,
'homepage' => false,
'donate_link' => false,
)
));
if (is_wp_error($api)) {
return false;
}
// Use a silent upgrader
$upgrader = new Plugin_Upgrader(new shop_toolkit_Pro_Silent_Upgrader_Skin());
$install = $upgrader->install($api->download_link);
return !is_wp_error($install) && $install;
} catch (Exception $e) {
return false;
}
}
/**
* Update local plugin from zip file
*/
private function update_local_plugin($plugin) {
try {
// Check if source file exists
if (!isset($plugin['source']) || !file_exists($plugin['source'])) {
return false;
}
// Deactivate plugin before update
if (is_plugin_active($plugin['file'])) {
deactivate_plugins($plugin['file'], true);
}
// Get plugin directory
$plugin_dir = WP_PLUGIN_DIR . '/' . dirname($plugin['file']);
// Remove existing plugin directory
if (is_dir($plugin_dir)) {
$this->delete_directory($plugin_dir);
}
// Extract new plugin
$result = $this->extract_plugin_zip($plugin['source'], WP_PLUGIN_DIR);
if ($result) {
// Reactivate plugin
activate_plugin($plugin['file'], '', false, true);
return true;
}
return false;
} catch (Exception $e) {
return false;
}
}
/**
* Update WordPress.org plugin
*/
private function update_wordpress_org_plugin($plugin_file) {
try {
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
// Load the silent upgrader skin class
shop_toolkit_load_silent_upgrader_skin();
$upgrader = new Plugin_Upgrader(new shop_toolkit_Pro_Silent_Upgrader_Skin());
$result = $upgrader->upgrade($plugin_file);
return !is_wp_error($result) && $result;
} catch (Exception $e) {
return false;
}
}
/**
* Activate plugin silently
*/
private function activate_plugin_silent($plugin) {
try {
$result = activate_plugin($plugin['file'], '', false, true);
return !is_wp_error($result);
} catch (Exception $e) {
return false;
}
}
/**
* Extract plugin zip file
*/
private function extract_plugin_zip($zip_file, $destination) {
if (!class_exists('ZipArchive')) {
error_log('Shop Toolkit Pro: ZipArchive class not available');
return false;
}
if (!file_exists($zip_file)) {
error_log('Shop Toolkit Pro: Zip file does not exist: ' . $zip_file);
return false;
}
if (!is_readable($zip_file)) {
error_log('Shop Toolkit Pro: Zip file is not readable: ' . $zip_file);
return false;
}
$zip = new ZipArchive();
$result = $zip->open($zip_file);
if ($result !== TRUE) {
$error_messages = array(
ZipArchive::ER_OK => 'No error',
ZipArchive::ER_MULTIDISK => 'Multi-disk zip archives not supported',
ZipArchive::ER_RENAME => 'Renaming temporary file failed',
ZipArchive::ER_CLOSE => 'Closing zip archive failed',
ZipArchive::ER_SEEK => 'Seek error',
ZipArchive::ER_READ => 'Read error',
ZipArchive::ER_WRITE => 'Write error',
ZipArchive::ER_CRC => 'CRC error',
ZipArchive::ER_ZIPCLOSED => 'Containing zip archive was closed',
ZipArchive::ER_NOENT => 'No such file',
ZipArchive::ER_EXISTS => 'File already exists',
ZipArchive::ER_OPEN => 'Can\'t open file',
ZipArchive::ER_TMPOPEN => 'Failure to create temporary file',
ZipArchive::ER_ZLIB => 'Zlib error',
ZipArchive::ER_MEMORY => 'Memory allocation failure',
ZipArchive::ER_CHANGED => 'Entry has been changed',
ZipArchive::ER_COMPNOTSUPP => 'Compression method not supported',
ZipArchive::ER_EOF => 'Premature EOF',
ZipArchive::ER_INVAL => 'Invalid argument',
ZipArchive::ER_NOZIP => 'Not a zip archive',
ZipArchive::ER_INTERNAL => 'Internal error',
ZipArchive::ER_INCONS => 'Zip archive inconsistent',
ZipArchive::ER_REMOVE => 'Can\'t remove file',
ZipArchive::ER_DELETED => 'Entry has been deleted',
);
$error_message = isset($error_messages[$result]) ? $error_messages[$result] : 'Unknown error';
error_log('Shop Toolkit Pro: Failed to open zip file: ' . $zip_file . ' (Error code: ' . $result . ' - ' . $error_message . ')');
return false;
}
// Log what's in the zip file for debugging
error_log('Shop Toolkit Pro: Zip file contains ' . $zip->numFiles . ' files');
for ($i = 0; $i < min($zip->numFiles, 10); $i++) {
$file_info = $zip->statIndex($i);
error_log('Shop Toolkit Pro: Zip file [' . $i . ']: ' . $file_info['name'] . ' (size: ' . $file_info['size'] . ')');
}
// Check if destination directory exists and is writable
if (!is_dir($destination)) {
error_log('Shop Toolkit Pro: Destination directory does not exist: ' . $destination);
$zip->close();
return false;
}
if (!is_writable($destination)) {
error_log('Shop Toolkit Pro: Destination directory is not writable: ' . $destination);
$zip->close();
return false;
}
// Extract to destination
$extract_result = $zip->extractTo($destination);
$extract_error = $extract_result ? 'Success' : 'Failed';
error_log('Shop Toolkit Pro: Extract result: ' . $extract_error . ' to ' . $destination);
if (!$extract_result) {
error_log('Shop Toolkit Pro: Extraction failed. Last error: ' . $zip->getStatusString());
}
$zip->close();
if (!$extract_result) {
error_log('Shop Toolkit Pro: Failed to extract zip file to: ' . $destination);
return false;
}
// Verify that files were actually extracted
$extracted_files = glob($destination . '/*');
if (empty($extracted_files)) {
error_log('Shop Toolkit Pro: No files found after extraction in: ' . $destination);
return false;
}
error_log('Shop Toolkit Pro: Successfully extracted ' . count($extracted_files) . ' items to: ' . $destination);
return true;
}
/**
* Delete directory recursively
*/
private function delete_directory($dir) {
if (!is_dir($dir)) {
return false;
}
$files = array_diff(scandir($dir), array('.', '..'));
foreach ($files as $file) {
$path = $dir . '/' . $file;
if (is_dir($path)) {
$this->delete_directory($path);
} else {
unlink($path);
}
}
return rmdir($dir);
}
/**
* Check if plugin installation/activation functions are available
*/
private function check_plugin_functions() {
if (!function_exists('is_plugin_active')) {
include_once ABSPATH . 'wp-admin/includes/plugin.php';
}
}
/**
* Migrate old notice dismissal to new system
*/
private function migrate_notice_dismissal() {
// Check if migration has already been done
if (get_option('shop_toolkit_notice_migration_done')) {
return;
}
// Reset old dismissals for migration
delete_user_meta(get_current_user_id(), 'shop_toolkit_hide_required_plugins_notice');
delete_user_meta(get_current_user_id(), 'shop_toolkit_hide_recommended_plugins_notice');
delete_user_meta(get_current_user_id(), 'shop_toolkit_hide_update_notice_time');
// Mark migration as done
update_option('shop_toolkit_notice_migration_done', true);
}
/**
* Check if all recommended plugins are active
*/
private function are_all_recommended_plugins_active() {
$all_plugins = $this->get_recommended_plugins();
foreach ($all_plugins as $plugin) {
if ($this->get_plugin_status($plugin) !== 'active') {
return false;
}
}
return true;
}
}
// Initialize the plugin recommendations
new shop_toolkit_Pro_Plugin_Recommendations();