PluginProbe
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets / 4.1.2
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets v4.1.2
4.5.4 4.2.1 4.2.2 4.2.3 4.5.0 4.5.2 4.5.3 4.2.0 4.1.18 4.1.17 4.1.16 4.1.15 4.1.14 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.0.9 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 All 146 releases
ultimate-post-kit / includes / setup-wizard / ultimate-post-kit-others-plugin.php

ultimate-post-kit-others-plugin.php in Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets 4.1.2, at includes/setup-wizard/ultimate-post-kit-others-plugin.php

586 lines 26.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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