| 1 |
<?php |
| 2 |
/** |
| 3 |
* Ultimate Post Kit Others Plugin - Standalone Plugin Manager |
| 4 |
* |
| 5 |
* This file provides the enhanced plugin installation and management system |
| 6 |
* for Ultimate Post Kit, separated from the main admin settings for better maintainability. |
| 7 |
* |
| 8 |
* @version 1.0.0 |
| 9 |
* @author BDThemes |
| 10 |
*/ |
| 11 |
|
| 12 |
if (!defined('ABSPATH')) { |
| 13 |
exit; |
| 14 |
} |
| 15 |
|
| 16 |
/** |
| 17 |
* Ultimate Post Kit Others Plugin Manager |
| 18 |
*/ |
| 19 |
class UltimatePostKit_Others_Plugin_Manager { |
| 20 |
|
| 21 |
/** |
| 22 |
* Constructor |
| 23 |
*/ |
| 24 |
public function __construct() { |
| 25 |
// Add AJAX handlers |
| 26 |
add_action('wp_ajax_upk_get_plugins', [$this, 'ajax_get_plugins']); |
| 27 |
add_action('wp_ajax_nopriv_upk_get_plugins', [$this, 'ajax_get_plugins']); |
| 28 |
add_action('wp_ajax_upk_install_plugin', [$this, 'install_plugin_ajax']); |
| 29 |
} |
| 30 |
|
| 31 |
/** |
| 32 |
* Render the others plugin interface |
| 33 |
*/ |
| 34 |
public function render_others_plugin() { |
| 35 |
// Include the required classes |
| 36 |
require_once BDTUPK_INC_PATH . 'setup-wizard/class-plugin-integration-helper.php'; |
| 37 |
require_once BDTUPK_INC_PATH . 'setup-wizard/class-remote-data-handler.php'; |
| 38 |
|
| 39 |
// Define plugin slugs for reference |
| 40 |
$plugin_slugs = array( |
| 41 |
'bdthemes-element-pack-lite', |
| 42 |
'bdthemes-prime-slider-lite/bdthemes-prime-slider.php', |
| 43 |
'ultimate-post-kit', |
| 44 |
'ultimate-store-kit', |
| 45 |
'zoloblocks', |
| 46 |
'pixel-gallery', |
| 47 |
'live-copy-paste', |
| 48 |
'spin-wheel', |
| 49 |
'ai-image', |
| 50 |
'dark-reader', |
| 51 |
'ar-viewer', |
| 52 |
'smart-admin-assistant', |
| 53 |
'website-accessibility', |
| 54 |
); |
| 55 |
|
| 56 |
// Helper function for time formatting |
| 57 |
if (!function_exists('format_last_updated_usk')) { |
| 58 |
function format_last_updated_usk($date_string) { |
| 59 |
if (empty($date_string)) { |
| 60 |
return __('Unknown', 'ultimate-post-kit'); |
| 61 |
} |
| 62 |
|
| 63 |
$date = strtotime($date_string); |
| 64 |
if (!$date) { |
| 65 |
return __('Unknown', 'ultimate-post-kit'); |
| 66 |
} |
| 67 |
|
| 68 |
$diff = current_time('timestamp') - $date; |
| 69 |
|
| 70 |
if ($diff < 60) { |
| 71 |
return __('Just now', 'ultimate-post-kit'); |
| 72 |
} elseif ($diff < 3600) { |
| 73 |
$minutes = floor($diff / 60); |
| 74 |
return sprintf(_n('%d minute ago', '%d minutes ago', $minutes, 'ultimate-post-kit'), $minutes); |
| 75 |
} elseif ($diff < 86400) { |
| 76 |
$hours = floor($diff / 3600); |
| 77 |
return sprintf(_n('%d hour ago', '%d hours ago', $hours, 'ultimate-post-kit'), $hours); |
| 78 |
} elseif ($diff < 2592000) { // 30 days |
| 79 |
$days = floor($diff / 86400); |
| 80 |
return sprintf(_n('%d day ago', '%d days ago', $days, 'ultimate-post-kit'), $days); |
| 81 |
} elseif ($diff < 31536000) { // 1 year |
| 82 |
$months = floor($diff / 2592000); |
| 83 |
return sprintf(_n('%d month ago', '%d months ago', $months, 'ultimate-post-kit'), $months); |
| 84 |
} else { |
| 85 |
$years = floor($diff / 31536000); |
| 86 |
return sprintf(_n('%d year ago', '%d years ago', $years, 'ultimate-post-kit'), $years); |
| 87 |
} |
| 88 |
} |
| 89 |
} |
| 90 |
|
| 91 |
// Helper function for fallback URLs |
| 92 |
if (!function_exists('get_plugin_fallback_urls_usk')) { |
| 93 |
function get_plugin_fallback_urls_usk($plugin_slug) { |
| 94 |
// Handle different plugin slug formats |
| 95 |
if (strpos($plugin_slug, '/') !== false) { |
| 96 |
// If it's a file path like 'plugin-name/plugin-name.php', extract directory |
| 97 |
$plugin_slug_clean = dirname($plugin_slug); |
| 98 |
} else { |
| 99 |
// If it's just the plugin directory name, use it directly |
| 100 |
$plugin_slug_clean = $plugin_slug; |
| 101 |
} |
| 102 |
|
| 103 |
// Custom icon URLs for specific plugins that might not be on WordPress.org |
| 104 |
$custom_icons = [ |
| 105 |
'ar-viewer' => [ |
| 106 |
'https://ps.w.org/ar-viewer/assets/icon-256x256.gif', |
| 107 |
'https://ps.w.org/ar-viewer/assets/icon-128x128.gif', |
| 108 |
], |
| 109 |
]; |
| 110 |
|
| 111 |
// Return custom icons if available, otherwise use default WordPress.org URLs |
| 112 |
if (isset($custom_icons[$plugin_slug_clean])) { |
| 113 |
return $custom_icons[$plugin_slug_clean]; |
| 114 |
} |
| 115 |
|
| 116 |
return [ |
| 117 |
"https://ps.w.org/{$plugin_slug_clean}/assets/icon-256x256.png", // Then PNG |
| 118 |
"https://ps.w.org/{$plugin_slug_clean}/assets/icon-128x128.png", // Medium PNG |
| 119 |
"https://ps.w.org/{$plugin_slug_clean}/assets/icon-256x256.gif", // Try GIF first |
| 120 |
"https://ps.w.org/{$plugin_slug_clean}/assets/icon-128x128.gif", // Medium GIF |
| 121 |
]; |
| 122 |
} |
| 123 |
} |
| 124 |
?> |
| 125 |
|
| 126 |
<div class="upk-dashboard-panel" |
| 127 |
bdt-scrollspy="target: > div > div > .bdt-card; cls: bdt-animation-slide-bottom-small; delay: 300"> |
| 128 |
<div class="upk-dashboard-others-plugin" id="upk-others-plugin-container"> |
| 129 |
|
| 130 |
<!-- Loading state --> |
| 131 |
<div class="upk-plugins-loading" id="upk-plugins-loading"> |
| 132 |
<div class="bdt-flex bdt-flex-center bdt-flex-middle bdt-text-center" style="min-height: 200px;"> |
| 133 |
<div> |
| 134 |
<div class="bdt-spinner bdt-spinner-primary"></div> |
| 135 |
<p class="bdt-margin-small-top"><?php esc_html_e('Loading plugin data...', 'ultimate-post-kit'); ?></p> |
| 136 |
</div> |
| 137 |
</div> |
| 138 |
</div> |
| 139 |
|
| 140 |
<!-- Error state (hidden by default) --> |
| 141 |
<div class="upk-plugins-error" id="upk-plugins-error" style="display: none;"> |
| 142 |
<div class="bdt-alert bdt-alert-warning" bdt-alert> |
| 143 |
<a class="bdt-alert-close" bdt-close></a> |
| 144 |
<p><?php esc_html_e('Unable to load plugin data. Please try again later.', 'ultimate-post-kit'); ?></p> |
| 145 |
<button class="bdt-button bdt-button-small bdt-margin-small-top" id="upk-retry-load-plugins"> |
| 146 |
<?php esc_html_e('Retry', 'ultimate-post-kit'); ?> |
| 147 |
</button> |
| 148 |
</div> |
| 149 |
</div> |
| 150 |
|
| 151 |
<!-- Plugins container (populated by AJAX) --> |
| 152 |
<div class="upk-plugins-list" id="upk-plugins-list" style="display: none;"> |
| 153 |
<!-- Plugin cards will be inserted here by JavaScript --> |
| 154 |
</div> |
| 155 |
</div> |
| 156 |
</div> |
| 157 |
|
| 158 |
<style type="text/css"> |
| 159 |
.upk-loading-spinner { |
| 160 |
position: absolute; |
| 161 |
top: 50%; |
| 162 |
left: 50%; |
| 163 |
transform: translate(-50%, -50%); |
| 164 |
text-align: center; |
| 165 |
} |
| 166 |
|
| 167 |
.upk-loading-dots { |
| 168 |
display: flex; |
| 169 |
justify-content: center; |
| 170 |
align-items: center; |
| 171 |
gap: 8px; |
| 172 |
margin-bottom: 15px; |
| 173 |
} |
| 174 |
|
| 175 |
.upk-loading-dot { |
| 176 |
width: 12px; |
| 177 |
height: 12px; |
| 178 |
background-color: #0073aa; |
| 179 |
border-radius: 50%; |
| 180 |
animation: upk-wave 1.4s ease-in-out infinite both; |
| 181 |
} |
| 182 |
|
| 183 |
.upk-loading-dot:nth-child(1) { animation-delay: -0.32s; } |
| 184 |
.upk-loading-dot:nth-child(2) { animation-delay: -0.16s; } |
| 185 |
.upk-loading-dot:nth-child(3) { animation-delay: 0; } |
| 186 |
|
| 187 |
@keyframes upk-wave { |
| 188 |
0%, 80%, 100% { |
| 189 |
transform: scale(0.8); |
| 190 |
opacity: 0.5; |
| 191 |
} |
| 192 |
40% { |
| 193 |
transform: scale(1.2); |
| 194 |
opacity: 1; |
| 195 |
} |
| 196 |
} |
| 197 |
|
| 198 |
#upk-plugins-list { |
| 199 |
position: relative; |
| 200 |
min-height: 200px; |
| 201 |
} |
| 202 |
</style> |
| 203 |
|
| 204 |
<script type="text/javascript"> |
| 205 |
jQuery(document).ready(function($) { |
| 206 |
var $container = $('#upk-others-plugin-container'); |
| 207 |
var $loading = $('#upk-plugins-loading'); |
| 208 |
var $error = $('#upk-plugins-error'); |
| 209 |
var $list = $('#upk-plugins-list'); |
| 210 |
|
| 211 |
// Function to load plugins via AJAX |
| 212 |
function loadPlugins() { |
| 213 |
$loading.hide(); |
| 214 |
$error.hide(); |
| 215 |
showLoading(); |
| 216 |
|
| 217 |
$.ajax({ |
| 218 |
url: ajaxurl, |
| 219 |
type: 'POST', |
| 220 |
data: { |
| 221 |
action: 'upk_get_plugins', |
| 222 |
nonce: '<?php echo wp_create_nonce("upk_get_plugins_nonce"); ?>' |
| 223 |
}, |
| 224 |
success: function(response) { |
| 225 |
if (response.success && response.data) { |
| 226 |
if (response.data.loading) { |
| 227 |
// Still loading, show message and retry after delay |
| 228 |
showLoading(); |
| 229 |
setTimeout(loadPlugins, 3000); // Retry after 3 seconds |
| 230 |
} else { |
| 231 |
renderPlugins(response.data.plugins); |
| 232 |
} |
| 233 |
} else { |
| 234 |
showError(); |
| 235 |
} |
| 236 |
}, |
| 237 |
error: function() { |
| 238 |
showError(); |
| 239 |
} |
| 240 |
}); |
| 241 |
} |
| 242 |
|
| 243 |
// Function to render plugins |
| 244 |
function renderPlugins(plugins) { |
| 245 |
var html = ''; |
| 246 |
|
| 247 |
if (plugins.length === 0) { |
| 248 |
html = '<div class="bdt-text-center bdt-padding-large"><p><?php esc_html_e('No plugins available.', 'ultimate-post-kit'); ?></p></div>'; |
| 249 |
} else { |
| 250 |
plugins.forEach(function(plugin) { |
| 251 |
// Skip own plugin (Ultimate Post Kit) when printing only; data still includes it for other plugins |
| 252 |
if (plugin.slug === 'ultimate-post-kit') return; |
| 253 |
var isActive = false; // We'll determine this via PHP in the actual implementation |
| 254 |
var logoUrl = plugin.logo || ''; |
| 255 |
var pluginName = plugin.name || ''; |
| 256 |
var pluginSlug = plugin.slug || ''; |
| 257 |
|
| 258 |
// Generate fallback logo URL if needed |
| 259 |
if (!logoUrl) { |
| 260 |
var actualSlug = pluginSlug.replace('.php', '').split('/')[0]; |
| 261 |
logoUrl = 'https://ps.w.org/' + actualSlug + '/assets/icon-256x256.png'; |
| 262 |
} |
| 263 |
|
| 264 |
html += '<div class="bdt-card bdt-card-body bdt-flex bdt-flex-middle bdt-flex-between">' + |
| 265 |
'<div class="bdt-others-plugin-content">' + |
| 266 |
'<div class="bdt-plugin-logo-wrap bdt-flex bdt-flex-middle">' + |
| 267 |
'<div class="bdt-plugin-logo-container">' + |
| 268 |
'<img src="' + logoUrl + '" alt="' + pluginName + '" class="bdt-plugin-logo" ' + |
| 269 |
'onerror="this.style.display=\'none\'; this.nextElementSibling.style.display=\'flex\';">' + |
| 270 |
'<div class="default-plugin-icon" style="display:none;">📦</div>' + |
| 271 |
'</div>' + |
| 272 |
'<div class="bdt-others-plugin-user-wrap bdt-flex bdt-flex-middle">' + |
| 273 |
'<h1 class="upk-feature-title">' + pluginName + '</h1>' + |
| 274 |
'</div>' + |
| 275 |
'</div>' + |
| 276 |
'<div class="bdt-others-plugin-content-text bdt-margin-top">'; |
| 277 |
|
| 278 |
if (plugin.description) { |
| 279 |
html += '<p>' + plugin.description + '</p>'; |
| 280 |
} |
| 281 |
|
| 282 |
// Active installs |
| 283 |
html += '<span class="active-installs bdt-margin-small-top">' + |
| 284 |
'<?php esc_html_e("Active Installs: ", "ultimate-post-kit"); ?> '; |
| 285 |
if (plugin.active_installs_count > 0) { |
| 286 |
html += '<span class="installs-count">' + plugin.active_installs_count.toLocaleString() + '+</span>'; |
| 287 |
} else { |
| 288 |
html += '<span class="installs-count">Fewer than 10</span>'; |
| 289 |
} |
| 290 |
html += '</span>'; |
| 291 |
|
| 292 |
// Rating |
| 293 |
html += '<div class="bdt-others-plugin-rating bdt-margin-small-top bdt-flex bdt-flex-middle">' + |
| 294 |
'<span class="bdt-others-plugin-rating-stars">'; |
| 295 |
|
| 296 |
var rating = parseFloat(plugin.rating) || 0; |
| 297 |
var fullStars = Math.floor(rating); |
| 298 |
var hasHalfStar = (rating - fullStars) >= 0.5; |
| 299 |
var emptyStars = 5 - fullStars - (hasHalfStar ? 1 : 0); |
| 300 |
|
| 301 |
for (var i = 0; i < fullStars; i++) { |
| 302 |
html += '<i class="dashicons dashicons-star-filled"></i>'; |
| 303 |
} |
| 304 |
if (hasHalfStar) { |
| 305 |
html += '<i class="dashicons dashicons-star-half"></i>'; |
| 306 |
} |
| 307 |
for (var i = 0; i < emptyStars; i++) { |
| 308 |
html += '<i class="dashicons dashicons-star-empty"></i>'; |
| 309 |
} |
| 310 |
|
| 311 |
html += '</span>' + |
| 312 |
'<span class="bdt-others-plugin-rating-text bdt-margin-small-left">' + |
| 313 |
rating + ' <?php esc_html_e("out of 5 stars.", "ultimate-post-kit"); ?>'; |
| 314 |
|
| 315 |
if (plugin.num_ratings > 0) { |
| 316 |
html += '<span class="rating-count">(' + plugin.num_ratings.toLocaleString() + ' <?php esc_html_e("ratings", "ultimate-post-kit"); ?>)</span>'; |
| 317 |
} |
| 318 |
|
| 319 |
html += '</span></div>'; |
| 320 |
|
| 321 |
// Downloads |
| 322 |
if (plugin.downloaded_formatted) { |
| 323 |
html += '<div class="bdt-others-plugin-downloads bdt-margin-small-top">' + |
| 324 |
'<span><?php esc_html_e("Downloads: ", "ultimate-post-kit"); ?>' + plugin.downloaded_formatted + '</span>' + |
| 325 |
'</div>'; |
| 326 |
} |
| 327 |
|
| 328 |
// Last updated |
| 329 |
if (plugin.last_updated_formatted) { |
| 330 |
html += '<div class="bdt-others-plugin-updated bdt-margin-small-top">' + |
| 331 |
'<span><?php esc_html_e("Last Updated: ", "ultimate-post-kit"); ?>' + plugin.last_updated_formatted + '</span>' + |
| 332 |
'</div>'; |
| 333 |
} |
| 334 |
|
| 335 |
html += '</div></div>' + |
| 336 |
'<div class="bdt-others-plugins-link">'; |
| 337 |
|
| 338 |
// Show different buttons based on plugin status |
| 339 |
if (plugin.status === 'active') { |
| 340 |
html += '<span class="bdt-button bdt-button-success bdt-disabled">' + |
| 341 |
'<span class="dashicons dashicons-yes"></span> ' + |
| 342 |
'<?php esc_html_e("Active", "ultimate-post-kit"); ?>' + |
| 343 |
'</span>'; |
| 344 |
} else if (plugin.status === 'installed') { |
| 345 |
var activateUrl = '<?php echo admin_url("plugins.php?action=activate&plugin="); ?>' + plugin.plugin_file + '&_wpnonce=' + plugin.activate_nonce; |
| 346 |
html += '<a class="bdt-button bdt-welcome-button" href="' + activateUrl + '">' + |
| 347 |
'<?php esc_html_e("Activate", "ultimate-post-kit"); ?>' + |
| 348 |
'</a>'; |
| 349 |
} else { |
| 350 |
html += '<button class="bdt-button bdt-welcome-button upk-install-plugin" data-plugin-slug="' + pluginSlug + '" data-nonce="<?php echo wp_create_nonce('upk_install_plugin_nonce'); ?>">' + |
| 351 |
'<?php esc_html_e("Install", "ultimate-post-kit"); ?>' + |
| 352 |
'</button>'; |
| 353 |
} |
| 354 |
|
| 355 |
if (plugin.homepage) { |
| 356 |
html += '<a class="bdt-button bdt-dashboard-sec-btn" target="_blank" href="' + plugin.homepage + '">' + |
| 357 |
'<?php esc_html_e("Learn More", "ultimate-post-kit"); ?>' + |
| 358 |
'</a>'; |
| 359 |
} |
| 360 |
|
| 361 |
html += '</div></div>'; |
| 362 |
}); |
| 363 |
} |
| 364 |
|
| 365 |
$list.html(html); |
| 366 |
|
| 367 |
// Handle plugin action buttons |
| 368 |
$('.upk-install-plugin').on('click', function(e) { |
| 369 |
e.preventDefault(); |
| 370 |
|
| 371 |
var $button = $(this); |
| 372 |
var pluginSlug = $button.data('plugin-slug'); |
| 373 |
var nonce = $button.data('nonce'); |
| 374 |
var originalText = $button.text(); |
| 375 |
|
| 376 |
// Disable button and show loading state |
| 377 |
$button.prop('disabled', true) |
| 378 |
.text('<?php echo esc_js(__('Installing...', 'ultimate-post-kit')); ?>') |
| 379 |
.addClass('bdt-installing'); |
| 380 |
|
| 381 |
// Perform AJAX request |
| 382 |
$.ajax({ |
| 383 |
url: '<?php echo admin_url('admin-ajax.php'); ?>', |
| 384 |
type: 'POST', |
| 385 |
data: { |
| 386 |
action: 'upk_install_plugin', |
| 387 |
plugin_slug: pluginSlug, |
| 388 |
nonce: nonce |
| 389 |
}, |
| 390 |
success: function(response) { |
| 391 |
if (response.success) { |
| 392 |
// Show success message |
| 393 |
$button.text('<?php echo esc_js(__('Installed!', 'ultimate-post-kit')); ?>') |
| 394 |
.removeClass('bdt-installing') |
| 395 |
.addClass('bdt-installed'); |
| 396 |
|
| 397 |
// Show success notification |
| 398 |
if (typeof bdtUIkit !== 'undefined' && bdtUIkit.notification) { |
| 399 |
bdtUIkit.notification({ |
| 400 |
message: '<span class="dashicons dashicons-yes"></span> ' + response.data.message, |
| 401 |
status: 'success' |
| 402 |
}); |
| 403 |
} |
| 404 |
|
| 405 |
// Reload the page after 2 seconds to update button states |
| 406 |
setTimeout(function() { |
| 407 |
window.location.reload(); |
| 408 |
}, 2000); |
| 409 |
|
| 410 |
} else { |
| 411 |
// Show error message |
| 412 |
$button.prop('disabled', false) |
| 413 |
.text(originalText) |
| 414 |
.removeClass('bdt-installing'); |
| 415 |
|
| 416 |
// Show error notification |
| 417 |
if (typeof bdtUIkit !== 'undefined' && bdtUIkit.notification) { |
| 418 |
bdtUIkit.notification({ |
| 419 |
message: '<span class="dashicons dashicons-warning"></span> ' + response.data.message, |
| 420 |
status: 'danger' |
| 421 |
}); |
| 422 |
} else { |
| 423 |
alert('Error: ' + response.data.message); |
| 424 |
} |
| 425 |
} |
| 426 |
}, |
| 427 |
error: function(xhr, status, error) { |
| 428 |
// Show error message |
| 429 |
$button.prop('disabled', false) |
| 430 |
.text(originalText) |
| 431 |
.removeClass('bdt-installing'); |
| 432 |
|
| 433 |
// Show error notification |
| 434 |
if (typeof bdtUIkit !== 'undefined' && bdtUIkit.notification) { |
| 435 |
bdtUIkit.notification({ |
| 436 |
message: '<span class="dashicons dashicons-warning"></span> <?php echo esc_js(__('Installation failed. Please try again.', 'ultimate-post-kit')); ?>', |
| 437 |
status: 'danger' |
| 438 |
}); |
| 439 |
} else { |
| 440 |
alert('<?php echo esc_js(__('Installation failed. Please try again.', 'ultimate-post-kit')); ?>'); |
| 441 |
} |
| 442 |
} |
| 443 |
}); |
| 444 |
}); |
| 445 |
} |
| 446 |
|
| 447 |
// Function to show loading state |
| 448 |
function showLoading() { |
| 449 |
$list.html( |
| 450 |
'<div class="bdt-text-center bdt-padding-large">' + |
| 451 |
'<div class="upk-loading-spinner">' + |
| 452 |
'<div class="upk-loading-dots">' + |
| 453 |
'<div class="upk-loading-dot"></div>' + |
| 454 |
'<div class="upk-loading-dot"></div>' + |
| 455 |
'<div class="upk-loading-dot"></div>' + |
| 456 |
'</div>' + |
| 457 |
'</div>' + |
| 458 |
'<p class="bdt-margin-small-top bdt-text-muted"><?php esc_html_e("Loading plugin data...", "ultimate-post-kit"); ?></p>' + |
| 459 |
'</div>' |
| 460 |
); |
| 461 |
$list.show(); |
| 462 |
} |
| 463 |
|
| 464 |
// Function to show error |
| 465 |
function showError() { |
| 466 |
$error.show(); |
| 467 |
$list.hide(); |
| 468 |
} |
| 469 |
|
| 470 |
// Retry button handler |
| 471 |
$('#upk-retry-load-plugins').on('click', function() { |
| 472 |
loadPlugins(); |
| 473 |
}); |
| 474 |
|
| 475 |
// Initial load |
| 476 |
loadPlugins(); |
| 477 |
}); |
| 478 |
</script> |
| 479 |
<?php |
| 480 |
} |
| 481 |
|
| 482 |
/** |
| 483 |
* AJAX handler for getting plugins data |
| 484 |
*/ |
| 485 |
public function ajax_get_plugins() { |
| 486 |
// Verify nonce |
| 487 |
if (!check_ajax_referer('upk_get_plugins_nonce', 'nonce', false)) { |
| 488 |
wp_die(__('Security check failed.', 'ultimate-post-kit')); |
| 489 |
} |
| 490 |
|
| 491 |
// Get cached data |
| 492 |
$plugins_data = \UltimatePostKit\SetupWizard\Remote_Data_Handler::get_remote_plugins(); |
| 493 |
|
| 494 |
// If cache is empty, try to fetch immediately (but don't block) |
| 495 |
if (empty($plugins_data)) { |
| 496 |
// Schedule background fetch if not already done |
| 497 |
\UltimatePostKit\SetupWizard\Remote_Data_Handler::schedule_remote_fetch(); |
| 498 |
|
| 499 |
// Return empty response with flag indicating data is loading |
| 500 |
wp_send_json_success([ |
| 501 |
'plugins' => [], |
| 502 |
'loading' => true, |
| 503 |
'message' => __('Loading plugin data...', 'ultimate-post-kit') |
| 504 |
]); |
| 505 |
} |
| 506 |
|
| 507 |
// Send response |
| 508 |
wp_send_json_success([ |
| 509 |
'plugins' => $plugins_data, |
| 510 |
'loading' => false, |
| 511 |
'message' => __('Plugin data loaded successfully.', 'ultimate-post-kit') |
| 512 |
]); |
| 513 |
} |
| 514 |
|
| 515 |
/** |
| 516 |
* AJAX handler for plugin installation |
| 517 |
*/ |
| 518 |
public function install_plugin_ajax() { |
| 519 |
// Check nonce |
| 520 |
if (!wp_verify_nonce($_POST['nonce'], 'upk_install_plugin_nonce')) { |
| 521 |
wp_send_json_error(['message' => __('Security check failed', 'ultimate-post-kit')]); |
| 522 |
} |
| 523 |
|
| 524 |
// Check user capability |
| 525 |
if (!current_user_can('install_plugins')) { |
| 526 |
wp_send_json_error(['message' => __('You do not have permission to install plugins', 'ultimate-post-kit')]); |
| 527 |
} |
| 528 |
|
| 529 |
$plugin_slug = sanitize_text_field($_POST['plugin_slug']); |
| 530 |
|
| 531 |
if (empty($plugin_slug)) { |
| 532 |
wp_send_json_error(['message' => __('Plugin slug is required', 'ultimate-post-kit')]); |
| 533 |
} |
| 534 |
|
| 535 |
// Include necessary WordPress files |
| 536 |
require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; |
| 537 |
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; |
| 538 |
require_once ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php'; |
| 539 |
|
| 540 |
// Get plugin information |
| 541 |
$api = plugins_api('plugin_information', [ |
| 542 |
'slug' => $plugin_slug, |
| 543 |
'fields' => [ |
| 544 |
'sections' => false, |
| 545 |
], |
| 546 |
]); |
| 547 |
|
| 548 |
if (is_wp_error($api)) { |
| 549 |
wp_send_json_error(['message' => __('Plugin not found: ', 'ultimate-post-kit') . $api->get_error_message()]); |
| 550 |
} |
| 551 |
|
| 552 |
// Install the plugin |
| 553 |
$skin = new \WP_Ajax_Upgrader_Skin(); |
| 554 |
$upgrader = new \Plugin_Upgrader($skin); |
| 555 |
$result = $upgrader->install($api->download_link); |
| 556 |
|
| 557 |
if (is_wp_error($result)) { |
| 558 |
wp_send_json_error(['message' => __('Installation failed: ', 'ultimate-post-kit') . $result->get_error_message()]); |
| 559 |
} elseif ($skin->get_errors()->has_errors()) { |
| 560 |
wp_send_json_error(['message' => __('Installation failed: ', 'ultimate-post-kit') . $skin->get_error_messages()]); |
| 561 |
} elseif (is_null($result)) { |
| 562 |
wp_send_json_error(['message' => __('Installation failed: Unable to connect to filesystem', 'ultimate-post-kit')]); |
| 563 |
} |
| 564 |
|
| 565 |
// Get installation status |
| 566 |
$install_status = install_plugin_install_status($api); |
| 567 |
|
| 568 |
wp_send_json_success([ |
| 569 |
'message' => __('Plugin installed successfully!', 'ultimate-post-kit'), |
| 570 |
'plugin_file' => $install_status['file'], |
| 571 |
'plugin_name' => $api->name |
| 572 |
]); |
| 573 |
} |
| 574 |
} |
| 575 |
|
| 576 |
// Initialize the manager |
| 577 |
new UltimatePostKit_Others_Plugin_Manager(); |
| 578 |
|
| 579 |
/** |
| 580 |
* Helper function for easy rendering |
| 581 |
*/ |
| 582 |
function ultimate_post_kit_others_plugin() { |
| 583 |
$manager = new UltimatePostKit_Others_Plugin_Manager(); |
| 584 |
$manager->render_others_plugin(); |
| 585 |
} |
| 586 |
|