617 lines
24 KiB
PHP
617 lines
24 KiB
PHP
<?php
|
|
/**
|
|
* The Recommended Plugins tab for plugin settings.
|
|
*
|
|
* @package SEO_Pro_Stack
|
|
* @subpackage SEO_Pro_Stack/Admin/Settings/Tabs
|
|
*/
|
|
|
|
// If this file is called directly, abort.
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* The Recommended Plugins tab for plugin settings.
|
|
* Self-contained class with integrated data and functionality
|
|
*/
|
|
class SEOProStack_Tab_Recommended_Plugins {
|
|
|
|
/**
|
|
* Tab identifier
|
|
*
|
|
* @var string
|
|
*/
|
|
private $tab_id = 'recommended-plugins';
|
|
|
|
/**
|
|
* Plugin details cache.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $plugin_details = array();
|
|
|
|
/**
|
|
* Initialize the class.
|
|
* Register any hooks or actions here.
|
|
*/
|
|
public function __construct() {
|
|
// Register AJAX handler for plugin installation
|
|
add_action('wp_ajax_seoprostack_install_plugins', array($this, 'ajax_install_plugins'));
|
|
|
|
// Define plugin names and descriptions for common plugins
|
|
$this->plugin_details = array(
|
|
'wordpress-seo' => array(
|
|
'name' => 'Yoast SEO (Free)',
|
|
'description' => 'The #1 WordPress SEO plugin that helps you with content optimization, XML sitemaps, and more.'
|
|
),
|
|
'autoptimize' => array(
|
|
'name' => 'Autoptimize',
|
|
'description' => 'Optimizes your website, concatenating scripts and styles, minifying and compressing them.'
|
|
),
|
|
'wp-fastest-cache' => array(
|
|
'name' => 'WP Fastest Cache',
|
|
'description' => 'This plugin creates static html files from your dynamic WordPress site to speed up your website.'
|
|
),
|
|
'updraftplus' => array(
|
|
'name' => 'UpdraftPlus',
|
|
'description' => 'Backup your website with ease, including files and database, and restore with one click.'
|
|
),
|
|
'google-site-kit' => array(
|
|
'name' => 'Site Kit by Google',
|
|
'description' => 'Get insights from multiple Google products directly in your WordPress dashboard.'
|
|
),
|
|
'wordfence' => array(
|
|
'name' => 'Wordfence Security',
|
|
'description' => 'Protect your site from malicious hackers with firewall and malware scanner.'
|
|
),
|
|
'rank-math-seo' => array(
|
|
'name' => 'Rank Math SEO',
|
|
'description' => 'SEO plugin that helps you rank higher in search engines with its powerful features and easy-to-use interface.'
|
|
),
|
|
'all-in-one-seo-pack' => array(
|
|
'name' => 'All in One SEO Pack',
|
|
'description' => 'Complete SEO solution for WordPress including on-page SEO optimization, XML sitemaps and more.'
|
|
),
|
|
'compressx' => array(
|
|
'name' => 'CompressX',
|
|
'description' => 'Comprehensive image optimization plugin for WordPress that improves page load speed.'
|
|
),
|
|
'wp-rocket' => array(
|
|
'name' => 'WP Rocket',
|
|
'description' => 'Premium caching plugin that improves site performance and page loading speed.'
|
|
),
|
|
'contact-form-7' => array(
|
|
'name' => 'Contact Form 7',
|
|
'description' => 'Simple but flexible contact form plugin with extensive customization options.'
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get the tab ID
|
|
*
|
|
* @return string The tab ID
|
|
*/
|
|
public function get_tab_id() {
|
|
return $this->tab_id;
|
|
}
|
|
|
|
/**
|
|
* Get the tab title
|
|
*
|
|
* @return string The tab title
|
|
*/
|
|
public function get_title() {
|
|
return __('Recommended Plugins', 'seoprostack');
|
|
}
|
|
|
|
/**
|
|
* Get the tab description
|
|
*
|
|
* @return string The tab description
|
|
*/
|
|
public function get_description() {
|
|
return __('These free plugins work well with SEO Pro Stack to enhance your WordPress site.', 'seoprostack');
|
|
}
|
|
|
|
/**
|
|
* Get recommended plugins
|
|
* This internalizes the data previously retrieved from wp_seoprostack_get_recommended_plugins()
|
|
*
|
|
* @return array Array of recommended plugins categorized by use case
|
|
*/
|
|
public function get_recommended_plugins() {
|
|
return array(
|
|
'minimal' => array(
|
|
'antispam-bee',
|
|
'compressx',
|
|
'fluent-smtp',
|
|
'kadence-blocks',
|
|
'simple-cloudflare-turnstile'
|
|
),
|
|
'admin' => array(
|
|
'admin-bar-dashboard-control',
|
|
'codepress-admin-columns',
|
|
'admin-menu-editor',
|
|
'hide-admin-notices',
|
|
'mainwp-child',
|
|
'mainwp-child-reports',
|
|
'magic-login',
|
|
'manage-notification-emails',
|
|
'plugin-groups',
|
|
'plugin-toggle'
|
|
),
|
|
'affiliates' => array(
|
|
'pretty-links',
|
|
'simple-urls',
|
|
'slicewp'
|
|
),
|
|
'ai' => array(
|
|
'ai-engine',
|
|
),
|
|
'cms' => array(
|
|
'auto-post-scheduler',
|
|
'block-options',
|
|
'bookmark-card',
|
|
'browser-shots',
|
|
'bulk-actions-select-all',
|
|
'bulk-edit-categories-tags',
|
|
'bulk-edit-user-profiles-in-spreadsheet',
|
|
'carbon-copy',
|
|
'code-block-pro',
|
|
'iframe-block',
|
|
'ics-calendar',
|
|
'mammoth-docx-converter',
|
|
'nav-menu-roles',
|
|
'ninja-tables',
|
|
'post-draft-preview',
|
|
'post-type-switcher',
|
|
'simple-custom-post-order',
|
|
'simple-icons',
|
|
'sticky-posts-switch',
|
|
'term-management-tools',
|
|
'the-paste',
|
|
'ultimate-addons-for-gutenberg',
|
|
'wikipedia-preview',
|
|
'wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages'
|
|
),
|
|
'compliance' => array(
|
|
'avatar-privacy',
|
|
'complianz-gdpr',
|
|
'complianz-terms-conditions',
|
|
'really-simple-ssl'
|
|
),
|
|
'crm' => array(
|
|
'fluent-boards',
|
|
'fluent-booking',
|
|
'fluent-community',
|
|
'fluent-crm',
|
|
'fluentform',
|
|
'fluentforms-pdf',
|
|
'fluentform-block',
|
|
'fluent-support'
|
|
),
|
|
'ecommerce' => array(
|
|
'woocommerce',
|
|
'woo-bulk-edit-products',
|
|
'woo-coupons-bulk-editor',
|
|
'woocommerce-gateway-gocardless',
|
|
'kadence-woocommerce-email-designer',
|
|
'pymntpl-paypal-woocommerce',
|
|
'woo-stripe-payment'
|
|
),
|
|
'lms' => array(
|
|
'fluent-community',
|
|
'masterstudy-lms-learning-management-system',
|
|
'tutor'
|
|
),
|
|
'media' => array(
|
|
'easy-watermark',
|
|
'enable-media-replace',
|
|
'image-copytrack',
|
|
'imsanity',
|
|
'media-file-renamer',
|
|
'safe-svg'
|
|
),
|
|
'seo' => array(
|
|
'burst-statistics',
|
|
'pretty-link',
|
|
'revive-so',
|
|
'seo-by-rank-math',
|
|
'syndication-links',
|
|
'ultimate-410',
|
|
'webmention'
|
|
),
|
|
'setup' => array(
|
|
'kadence-starter-templates',
|
|
'wordpress-importer'
|
|
),
|
|
'social' => array(
|
|
'bit-social',
|
|
'easy-video-reviews',
|
|
'social-engine',
|
|
'wp-social-ninja',
|
|
'wp-social-reviews'
|
|
),
|
|
'speed' => array(
|
|
'disable-wordpress-updates',
|
|
'flying-analytics',
|
|
'flying-pages',
|
|
'flying-scripts',
|
|
'freesoul-deactivate-plugins',
|
|
'index-wp-mysql-for-speed',
|
|
'litespeed-cache',
|
|
'performant-translations',
|
|
'wp-optimize',
|
|
'wp-widget-disable'
|
|
),
|
|
'translation' => array(
|
|
'hreflang-manager-lite',
|
|
'performant-translations',
|
|
'translatepress-multilingual'
|
|
),
|
|
'advanced' => array(
|
|
'acf-better-search',
|
|
'advanced-custom-fields',
|
|
'automatorwp',
|
|
'bit-pi',
|
|
'bit-integrations',
|
|
'code-snippets',
|
|
'easy-code-manager',
|
|
'favorites',
|
|
'remove-cpt-base',
|
|
'remove-old-slugspermalinks',
|
|
'secure-custom-fields',
|
|
'yellow-pencil-visual-theme-customizer'
|
|
),
|
|
'debug' => array(
|
|
'advanced-database-cleaner',
|
|
'debug-log-manager',
|
|
'gotmls',
|
|
'query-monitor',
|
|
'string-locator',
|
|
'user-switching',
|
|
'wp-crontrol'
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Render the tab content.
|
|
*/
|
|
public function render() {
|
|
// Get recommended plugins from the internal method
|
|
$recommended_plugins = $this->get_recommended_plugins();
|
|
|
|
// For backward compatibility, make recommended plugins available through global function
|
|
if (function_exists('wp_seoprostack_get_recommended_plugins') && empty($GLOBALS['_wp_seoprostack_recommended_plugins_loaded'])) {
|
|
// Optional: merge with any plugins from the external function to ensure none are lost
|
|
$external_plugins = wp_seoprostack_get_recommended_plugins();
|
|
$recommended_plugins = array_merge_recursive($external_plugins, $recommended_plugins);
|
|
$GLOBALS['_wp_seoprostack_recommended_plugins_loaded'] = true;
|
|
}
|
|
|
|
?>
|
|
<div class="seoprostack-settings-content tab-content" id="<?php echo esc_attr($this->get_tab_id()); ?>">
|
|
<div class="seoprostack-setting-section">
|
|
<h2><?php esc_html_e('Recommended Free Plugins', 'seoprostack'); ?></h2>
|
|
<p class="description"><?php echo esc_html($this->get_description()); ?></p>
|
|
|
|
<?php
|
|
// Display SEO plugins section
|
|
if (!empty($recommended_plugins['seo'])) {
|
|
echo '<h3>' . esc_html__('SEO Plugins', 'seoprostack') . '</h3>';
|
|
echo '<div class="seoprostack-plugin-grid">';
|
|
foreach ($recommended_plugins['seo'] as $plugin_slug) {
|
|
$this->render_plugin_card($plugin_slug);
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
// Display Cache plugins section
|
|
if (!empty($recommended_plugins['speed'])) {
|
|
echo '<h3>' . esc_html__('Cache & Performance', 'seoprostack') . '</h3>';
|
|
echo '<div class="seoprostack-plugin-grid">';
|
|
foreach ($recommended_plugins['speed'] as $plugin_slug) {
|
|
$this->render_plugin_card($plugin_slug);
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
// Display Security plugins section
|
|
if (!empty($recommended_plugins['security'])) {
|
|
echo '<h3>' . esc_html__('Security', 'seoprostack') . '</h3>';
|
|
echo '<div class="seoprostack-plugin-grid">';
|
|
foreach ($recommended_plugins['security'] as $plugin_slug) {
|
|
$this->render_plugin_card($plugin_slug);
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
// Display Image optimization plugins section
|
|
if (!empty($recommended_plugins['media'])) {
|
|
echo '<h3>' . esc_html__('Image Optimization', 'seoprostack') . '</h3>';
|
|
echo '<div class="seoprostack-plugin-grid">';
|
|
foreach ($recommended_plugins['media'] as $plugin_slug) {
|
|
$this->render_plugin_card($plugin_slug);
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
// Display Backup plugins section
|
|
if (!empty($recommended_plugins['backup'])) {
|
|
echo '<h3>' . esc_html__('Backup & Migration', 'seoprostack') . '</h3>';
|
|
echo '<div class="seoprostack-plugin-grid">';
|
|
foreach ($recommended_plugins['backup'] as $plugin_slug) {
|
|
$this->render_plugin_card($plugin_slug);
|
|
}
|
|
echo '</div>';
|
|
}
|
|
?>
|
|
|
|
<div class="seoprostack-bulk-actions">
|
|
<button class="button button-primary" id="seoprostack-install-selected">
|
|
<?php esc_html_e('Install Selected Plugins', 'seoprostack'); ?>
|
|
</button>
|
|
<span class="spinner"></span>
|
|
</div>
|
|
|
|
<div id="seoprostack-install-response"></div>
|
|
|
|
<script type="text/javascript">
|
|
jQuery(document).ready(function($) {
|
|
// Handle bulk installation
|
|
$('#seoprostack-install-selected').on('click', function(e) {
|
|
e.preventDefault();
|
|
|
|
var $button = $(this);
|
|
var $spinner = $button.next('.spinner');
|
|
var $response = $('#seoprostack-install-response');
|
|
var selected = [];
|
|
|
|
// Get selected plugins
|
|
$('.seoprostack-plugin-check:checked').each(function() {
|
|
selected.push($(this).val());
|
|
});
|
|
|
|
if (selected.length === 0) {
|
|
$response.html('<div class="seoprostack-notice seoprostack-notice-warning">Please select at least one plugin to install</div>');
|
|
return;
|
|
}
|
|
|
|
// Show loading
|
|
$button.prop('disabled', true);
|
|
$spinner.css('visibility', 'visible');
|
|
$response.html('<div class="seoprostack-notice seoprostack-notice-loading">Installing plugins...</div>');
|
|
|
|
// Send AJAX request
|
|
$.ajax({
|
|
url: wpSeoProStack.ajaxurl,
|
|
type: 'POST',
|
|
data: {
|
|
action: 'seoprostack_install_plugins',
|
|
plugins: selected,
|
|
nonce: wpSeoProStack.nonce
|
|
},
|
|
success: function(response) {
|
|
// Hide loading
|
|
$button.prop('disabled', false);
|
|
$spinner.css('visibility', 'hidden');
|
|
|
|
if (response.success) {
|
|
var html = '<div class="seoprostack-notice seoprostack-notice-success">';
|
|
html += '<p>Installation completed:</p><ul>';
|
|
|
|
$.each(response.data.installed, function(i, plugin) {
|
|
html += '<li>' + plugin + ' installed and activated successfully</li>';
|
|
// Update UI
|
|
$('.seoprostack-plugin-card[data-slug="' + plugin + '"]')
|
|
.find('.plugin-status')
|
|
.removeClass('not-installed')
|
|
.addClass('active')
|
|
.text('Active');
|
|
});
|
|
|
|
if (response.data.failed.length > 0) {
|
|
html += '</ul><p>Installation failed:</p><ul>';
|
|
$.each(response.data.failed, function(i, fail) {
|
|
html += '<li>' + fail.plugin + ': ' + fail.message + '</li>';
|
|
});
|
|
}
|
|
|
|
html += '</ul></div>';
|
|
$response.html(html);
|
|
} else {
|
|
$response.html('<div class="seoprostack-notice seoprostack-notice-error">' + response.data.message + '</div>');
|
|
}
|
|
},
|
|
error: function() {
|
|
// Hide loading
|
|
$button.prop('disabled', false);
|
|
$spinner.css('visibility', 'hidden');
|
|
|
|
// Show error
|
|
$response.html('<div class="seoprostack-notice seoprostack-notice-error">Error connecting to server</div>');
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Render a plugin card.
|
|
*
|
|
* @param string $slug The plugin slug.
|
|
*/
|
|
private function render_plugin_card($slug) {
|
|
// Get plugin details
|
|
$name = isset($this->plugin_details[$slug]['name']) ? $this->plugin_details[$slug]['name'] : $this->get_readable_name($slug);
|
|
$description = isset($this->plugin_details[$slug]['description']) ? $this->plugin_details[$slug]['description'] : '';
|
|
|
|
// Check if plugin is installed and active
|
|
$status = 'not-installed';
|
|
$status_text = 'Not Installed';
|
|
|
|
if (file_exists(WP_PLUGIN_DIR . '/' . $slug)) {
|
|
$status = 'installed';
|
|
$status_text = 'Installed';
|
|
|
|
include_once ABSPATH . 'wp-admin/includes/plugin.php';
|
|
if (is_plugin_active($slug . '/' . $slug . '.php') || is_plugin_active($slug . '/index.php')) {
|
|
$status = 'active';
|
|
$status_text = 'Active';
|
|
}
|
|
}
|
|
|
|
?>
|
|
<div class="seoprostack-plugin-card" data-slug="<?php echo esc_attr($slug); ?>">
|
|
<div class="seoprostack-plugin-card-header">
|
|
<label class="seoprostack-checkbox-container">
|
|
<input type="checkbox" class="seoprostack-plugin-check" value="<?php echo esc_attr($slug); ?>" <?php disabled($status === 'active', true); ?>>
|
|
<span class="seoprostack-checkbox-checkmark"></span>
|
|
</label>
|
|
|
|
<span class="plugin-status <?php echo esc_attr($status); ?>"><?php echo esc_html($status_text); ?></span>
|
|
</div>
|
|
|
|
<div class="seoprostack-plugin-card-content">
|
|
<h3><?php echo esc_html($name); ?></h3>
|
|
<?php if (!empty($description)) : ?>
|
|
<p><?php echo esc_html($description); ?></p>
|
|
<?php endif; ?>
|
|
|
|
<div class="seoprostack-plugin-card-footer">
|
|
<a href="https://wordpress.org/plugins/<?php echo esc_attr($slug); ?>/" class="button button-secondary" target="_blank">
|
|
<?php esc_html_e('View Details', 'seoprostack'); ?>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Get a readable name from a plugin slug.
|
|
*
|
|
* @param string $slug The plugin slug.
|
|
* @return string The readable name.
|
|
*/
|
|
private function get_readable_name($slug) {
|
|
$name = str_replace(array('-', '_'), ' ', $slug);
|
|
return ucwords($name);
|
|
}
|
|
|
|
/**
|
|
* AJAX handler for plugin installation
|
|
*/
|
|
public function ajax_install_plugins() {
|
|
// Check nonce for security
|
|
check_ajax_referer('wp-seoprostack-nonce', 'nonce');
|
|
|
|
// Ensure user has permission
|
|
if (!current_user_can('install_plugins')) {
|
|
wp_send_json_error(array('message' => __('You do not have permission to install plugins.', 'seoprostack')));
|
|
}
|
|
|
|
// Get selected plugins
|
|
$plugins = isset($_POST['plugins']) ? (array) $_POST['plugins'] : array();
|
|
|
|
if (empty($plugins)) {
|
|
wp_send_json_error(array('message' => __('No plugins selected.', 'seoprostack')));
|
|
}
|
|
|
|
// Include required files for plugin installation
|
|
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
|
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
|
|
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
|
require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
|
|
|
|
// Set up the upgrader
|
|
$skin = new WP_Ajax_Upgrader_Skin();
|
|
$upgrader = new Plugin_Upgrader($skin);
|
|
|
|
$installed = array();
|
|
$failed = array();
|
|
|
|
// Install and activate each plugin
|
|
foreach ($plugins as $plugin) {
|
|
// Skip if already active
|
|
if (is_plugin_active($plugin . '/' . $plugin . '.php') || is_plugin_active($plugin . '/index.php')) {
|
|
continue;
|
|
}
|
|
|
|
// Get plugin info from wordpress.org
|
|
$api = plugins_api('plugin_information', array(
|
|
'slug' => $plugin,
|
|
'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)) {
|
|
$failed[] = array(
|
|
'plugin' => $plugin,
|
|
'message' => $api->get_error_message()
|
|
);
|
|
continue;
|
|
}
|
|
|
|
// Install the plugin
|
|
$result = $upgrader->install($api->download_link);
|
|
|
|
if (is_wp_error($result)) {
|
|
$failed[] = array(
|
|
'plugin' => $plugin,
|
|
'message' => $result->get_error_message()
|
|
);
|
|
continue;
|
|
}
|
|
|
|
if ($result === false) {
|
|
$failed[] = array(
|
|
'plugin' => $plugin,
|
|
'message' => __('Failed to install plugin.', 'seoprostack')
|
|
);
|
|
continue;
|
|
}
|
|
|
|
// Activate the plugin
|
|
$activate = activate_plugin(WP_PLUGIN_DIR . '/' . $plugin . '/' . $plugin . '.php');
|
|
if (is_wp_error($activate)) {
|
|
// Try alternative file path
|
|
$activate = activate_plugin(WP_PLUGIN_DIR . '/' . $plugin . '/index.php');
|
|
if (is_wp_error($activate)) {
|
|
$failed[] = array(
|
|
'plugin' => $plugin,
|
|
'message' => $activate->get_error_message()
|
|
);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
$installed[] = $plugin;
|
|
}
|
|
|
|
// Send success response
|
|
wp_send_json_success(array(
|
|
'installed' => $installed,
|
|
'failed' => $failed
|
|
));
|
|
}
|
|
}
|