activity-reports.php
2 hours ago
author-dashboard.php
5 years ago
basic.php
5 months ago
buddypress.php
5 years ago
cloud-storage.php
5 years ago
cron-jobs.php
2 hours ago
crons.php
1 year ago
frontend.php
2 years ago
privacy.php
8 months ago
profile-dashboard.php
5 years ago
social-connects.php
5 years ago
user-interface.php
4 months ago
cron-jobs.php
285 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Cron Jobs Settings Tab |
| 4 | * |
| 5 | * Admin UI for managing WPDM cron jobs. |
| 6 | * |
| 7 | * @package WPDM\Admin |
| 8 | * @since 7.0.1 |
| 9 | */ |
| 10 | |
| 11 | if (!defined('ABSPATH')) exit; |
| 12 | |
| 13 | use WPDM\__\CronJob; |
| 14 | use WPDM\__\CronJobs; |
| 15 | |
| 16 | $counts = CronJob::getCounts(); |
| 17 | $jobs = CronJob::getAll(['limit' => 50, 'orderby' => 'created_at', 'order' => 'DESC']); |
| 18 | $scheduledEvents = CronJobs::getScheduledEvents(); |
| 19 | $cronUrl = CronJobs::getCronUrl(); |
| 20 | $isWpCronDisabled = CronJobs::isWpCronDisabled(); |
| 21 | ?> |
| 22 | |
| 23 | <style> |
| 24 | .wpdm-cron-stats { |
| 25 | display: flex; |
| 26 | gap: 10px; |
| 27 | margin-bottom: 20px; |
| 28 | } |
| 29 | .wpdm-cron-stat { |
| 30 | flex: 1; |
| 31 | text-align: center; |
| 32 | padding: 15px; |
| 33 | background: #fff; |
| 34 | border: 1px solid #e5e7eb; |
| 35 | border-radius: 8px; |
| 36 | } |
| 37 | .wpdm-cron-stat-value { |
| 38 | font-size: 24px; |
| 39 | font-weight: 700; |
| 40 | color: #1e293b; |
| 41 | } |
| 42 | .wpdm-cron-stat-value.text-warning { color: #f59e0b; } |
| 43 | .wpdm-cron-stat-value.text-info { color: #3b82f6; } |
| 44 | .wpdm-cron-stat-value.text-success { color: #10b981; } |
| 45 | .wpdm-cron-stat-value.text-danger { color: #ef4444; } |
| 46 | .wpdm-cron-stat-label { |
| 47 | font-size: 11px; |
| 48 | color: #64748b; |
| 49 | text-transform: uppercase; |
| 50 | margin-top: 4px; |
| 51 | } |
| 52 | </style> |
| 53 | |
| 54 | <!-- Stats --> |
| 55 | <div class="wpdm-cron-stats"> |
| 56 | <div class="wpdm-cron-stat"> |
| 57 | <div class="wpdm-cron-stat-value"><?php echo esc_html($counts['total']); ?></div> |
| 58 | <div class="wpdm-cron-stat-label"><?php esc_html_e('Total Jobs', 'download-manager'); ?></div> |
| 59 | </div> |
| 60 | <div class="wpdm-cron-stat"> |
| 61 | <div class="wpdm-cron-stat-value text-warning"><?php echo esc_html($counts[CronJob::STATUS_PENDING]); ?></div> |
| 62 | <div class="wpdm-cron-stat-label"><?php esc_html_e('Pending', 'download-manager'); ?></div> |
| 63 | </div> |
| 64 | <div class="wpdm-cron-stat"> |
| 65 | <div class="wpdm-cron-stat-value text-info"><?php echo esc_html($counts[CronJob::STATUS_RUNNING]); ?></div> |
| 66 | <div class="wpdm-cron-stat-label"><?php esc_html_e('Running', 'download-manager'); ?></div> |
| 67 | </div> |
| 68 | <div class="wpdm-cron-stat"> |
| 69 | <div class="wpdm-cron-stat-value text-success"><?php echo esc_html($counts[CronJob::STATUS_COMPLETED]); ?></div> |
| 70 | <div class="wpdm-cron-stat-label"><?php esc_html_e('Completed', 'download-manager'); ?></div> |
| 71 | </div> |
| 72 | <div class="wpdm-cron-stat"> |
| 73 | <div class="wpdm-cron-stat-value text-danger"><?php echo esc_html($counts[CronJob::STATUS_FAILED]); ?></div> |
| 74 | <div class="wpdm-cron-stat-label"><?php esc_html_e('Failed', 'download-manager'); ?></div> |
| 75 | </div> |
| 76 | </div> |
| 77 | |
| 78 | <?php if ($isWpCronDisabled): ?> |
| 79 | <!-- WP Cron Disabled Warning --> |
| 80 | <div class="alert alert-warning"> |
| 81 | <strong><?php esc_html_e('WordPress Cron is Disabled', 'download-manager'); ?></strong><br> |
| 82 | <?php esc_html_e('DISABLE_WP_CRON is set to true. You need to set up a real cron job to process the job queue. Use the URL below with a cron service or server cron.', 'download-manager'); ?> |
| 83 | </div> |
| 84 | <?php endif; ?> |
| 85 | |
| 86 | <!-- External Cron URL --> |
| 87 | <div class="panel panel-default"> |
| 88 | <div class="panel-heading"><?php esc_html_e('External Cron URL', 'download-manager'); ?></div> |
| 89 | <div class="panel-body"> |
| 90 | <p class="text-muted" style="margin-bottom: 10px;"> |
| 91 | <?php esc_html_e('Use this URL to trigger job processing from an external cron service. Add this to your server crontab or use a service like EasyCron.', 'download-manager'); ?> |
| 92 | </p> |
| 93 | <div class="input-group"> |
| 94 | <input type="text" id="wpdm-cron-url" value="<?php echo esc_attr($cronUrl); ?>" class="form-control" readonly> |
| 95 | <div class="input-group-btn"> |
| 96 | <button onclick="WPDM.copy('wpdm-cron-url')" type="button" class="btn btn-secondary ttip" title="Copy"> |
| 97 | <i class="fa fa-copy"></i> |
| 98 | </button> |
| 99 | </div> |
| 100 | </div> |
| 101 | </div> |
| 102 | </div> |
| 103 | |
| 104 | <!-- Scheduled Events --> |
| 105 | <div class="panel panel-default"> |
| 106 | <div class="panel-heading"><?php esc_html_e('Scheduled WordPress Cron Events', 'download-manager'); ?></div> |
| 107 | <table class="table table-striped"> |
| 108 | <thead> |
| 109 | <tr> |
| 110 | <th><?php esc_html_e('Hook', 'download-manager'); ?></th> |
| 111 | <th><?php esc_html_e('Description', 'download-manager'); ?></th> |
| 112 | <th><?php esc_html_e('Next Run', 'download-manager'); ?></th> |
| 113 | </tr> |
| 114 | </thead> |
| 115 | <tbody> |
| 116 | <?php foreach ($scheduledEvents as $hook => $event): ?> |
| 117 | <tr> |
| 118 | <td><code><?php echo esc_html($hook); ?></code></td> |
| 119 | <td><?php echo esc_html($event['description']); ?></td> |
| 120 | <td> |
| 121 | <?php if ($event['next_run']): ?> |
| 122 | <?php echo esc_html(date_i18n('M j, Y H:i:s', $event['next_run'])); ?> |
| 123 | <?php else: ?> |
| 124 | <span class="text-danger"><?php esc_html_e('Not scheduled', 'download-manager'); ?></span> |
| 125 | <?php endif; ?> |
| 126 | </td> |
| 127 | </tr> |
| 128 | <?php endforeach; ?> |
| 129 | </tbody> |
| 130 | </table> |
| 131 | </div> |
| 132 | |
| 133 | <!-- Actions --> |
| 134 | <p> |
| 135 | <button type="button" class="btn btn-success" id="wpdm-run-cron"> |
| 136 | <i class="fa fa-play"></i> <?php esc_html_e('Run Job Queue Now', 'download-manager'); ?> |
| 137 | </button> |
| 138 | </p> |
| 139 | |
| 140 | <!-- Jobs Table --> |
| 141 | <div class="panel panel-default"> |
| 142 | <div class="panel-heading"><?php esc_html_e('Recent Jobs', 'download-manager'); ?></div> |
| 143 | <?php if (empty($jobs)): ?> |
| 144 | <div class="panel-body" style="text-align: center; padding: 40px;"> |
| 145 | <img src="<?php echo WPDM_ASSET_URL; ?>/images/no-job.png" style="width: 128px; padding: 20px;" /><br/> |
| 146 | <p class="lead"><?php esc_html_e('No jobs in the queue yet.', 'download-manager'); ?></p> |
| 147 | </div> |
| 148 | <?php else: ?> |
| 149 | <div style="overflow-x: auto;"> |
| 150 | <table class="table table-striped"> |
| 151 | <thead> |
| 152 | <tr> |
| 153 | <th><?php esc_html_e('ID', 'download-manager'); ?></th> |
| 154 | <th><?php esc_html_e('Type', 'download-manager'); ?></th> |
| 155 | <th><?php esc_html_e('Queue', 'download-manager'); ?></th> |
| 156 | <th><?php esc_html_e('Status', 'download-manager'); ?></th> |
| 157 | <th><?php esc_html_e('Attempts', 'download-manager'); ?></th> |
| 158 | <th><?php esc_html_e('Execute At', 'download-manager'); ?></th> |
| 159 | <th><?php esc_html_e('Actions', 'download-manager'); ?></th> |
| 160 | </tr> |
| 161 | </thead> |
| 162 | <tbody> |
| 163 | <?php foreach ($jobs as $job): ?> |
| 164 | <tr id="job-<?php echo esc_attr($job->ID); ?>"> |
| 165 | <td>#<?php echo esc_html($job->ID); ?></td> |
| 166 | <td> |
| 167 | <?php |
| 168 | $typeParts = explode('\\', $job->type); |
| 169 | echo '<code>' . esc_html(end($typeParts)) . '</code>'; |
| 170 | ?> |
| 171 | </td> |
| 172 | <td><?php echo esc_html($job->queue ?? 'default'); ?></td> |
| 173 | <td> |
| 174 | <?php |
| 175 | $status = $job->status ?? 'pending'; |
| 176 | $statusClass = [ |
| 177 | 'pending' => 'btn-warning', |
| 178 | 'running' => 'btn-info', |
| 179 | 'completed' => 'btn-success', |
| 180 | 'failed' => 'btn-danger', |
| 181 | 'cancelled' => 'btn-secondary', |
| 182 | ][$status] ?? 'btn-secondary'; |
| 183 | ?> |
| 184 | <span class="btn btn-xs <?php echo esc_attr($statusClass); ?>" style="cursor: default;"> |
| 185 | <?php echo esc_html(ucfirst($status)); ?> |
| 186 | </span> |
| 187 | </td> |
| 188 | <td><?php echo esc_html(($job->attempts ?? 0) . '/' . ($job->max_attempts ?? 3)); ?></td> |
| 189 | <td> |
| 190 | <?php |
| 191 | if ($job->execute_at) { |
| 192 | echo esc_html(date_i18n('M j, H:i', $job->execute_at)); |
| 193 | } else { |
| 194 | echo '-'; |
| 195 | } |
| 196 | ?> |
| 197 | </td> |
| 198 | <td> |
| 199 | <?php if (($job->status ?? 'pending') === 'pending'): ?> |
| 200 | <button type="button" class="btn btn-success btn-xs wpdm-job-action" data-action="run_now" data-job="<?php echo esc_attr($job->ID); ?>"> |
| 201 | <?php esc_html_e('Run', 'download-manager'); ?> |
| 202 | </button> |
| 203 | <button type="button" class="btn btn-secondary btn-xs wpdm-job-action" data-action="cancel" data-job="<?php echo esc_attr($job->ID); ?>"> |
| 204 | <?php esc_html_e('Cancel', 'download-manager'); ?> |
| 205 | </button> |
| 206 | <?php elseif (($job->status ?? '') === 'failed'): ?> |
| 207 | <button type="button" class="btn btn-info btn-xs wpdm-job-action" data-action="retry" data-job="<?php echo esc_attr($job->ID); ?>"> |
| 208 | <?php esc_html_e('Retry', 'download-manager'); ?> |
| 209 | </button> |
| 210 | <?php endif; ?> |
| 211 | <button type="button" class="btn btn-danger btn-xs wpdm-job-action" data-action="delete" data-job="<?php echo esc_attr($job->ID); ?>"> |
| 212 | <?php esc_html_e('Delete', 'download-manager'); ?> |
| 213 | </button> |
| 214 | </td> |
| 215 | </tr> |
| 216 | <?php endforeach; ?> |
| 217 | </tbody> |
| 218 | </table> |
| 219 | </div> |
| 220 | <?php endif; ?> |
| 221 | </div> |
| 222 | |
| 223 | <script> |
| 224 | jQuery(function($) { |
| 225 | var nonce = '<?php echo wp_create_nonce('wpdm_job_action'); ?>'; |
| 226 | var cronNonce = '<?php echo wp_create_nonce('wpdm_cron_nonce'); ?>'; |
| 227 | |
| 228 | // Run cron button |
| 229 | $('#wpdm-run-cron').on('click', function() { |
| 230 | var $btn = $(this); |
| 231 | if ($btn.prop('disabled')) return; |
| 232 | |
| 233 | $btn.prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> Running...'); |
| 234 | |
| 235 | $.post(ajaxurl, { |
| 236 | action: 'wpdm_run_cron', |
| 237 | nonce: cronNonce |
| 238 | }, function(response) { |
| 239 | $btn.prop('disabled', false).html('<i class="fa fa-play"></i> Run Job Queue Now'); |
| 240 | |
| 241 | if (response.success) { |
| 242 | var r = response.data.results; |
| 243 | alert('Processed: ' + r.processed + ', Succeeded: ' + r.succeeded + ', Failed: ' + r.failed); |
| 244 | location.reload(); |
| 245 | } else { |
| 246 | alert(response.data.message || 'Failed to run cron'); |
| 247 | } |
| 248 | }).fail(function() { |
| 249 | $btn.prop('disabled', false).html('<i class="fa fa-play"></i> Run Job Queue Now'); |
| 250 | alert('Request failed'); |
| 251 | }); |
| 252 | }); |
| 253 | |
| 254 | // Job actions |
| 255 | $(document).on('click', '.wpdm-job-action', function() { |
| 256 | var $btn = $(this); |
| 257 | var action = $btn.data('action'); |
| 258 | var jobId = $btn.data('job'); |
| 259 | |
| 260 | if (action === 'delete' && !confirm('<?php esc_html_e('Are you sure you want to delete this job?', 'download-manager'); ?>')) { |
| 261 | return; |
| 262 | } |
| 263 | |
| 264 | $btn.prop('disabled', true).text('...'); |
| 265 | |
| 266 | $.post(ajaxurl, { |
| 267 | action: 'wpdm_job_action', |
| 268 | nonce: nonce, |
| 269 | job_action: action, |
| 270 | job_id: jobId |
| 271 | }, function(response) { |
| 272 | if (response.success) { |
| 273 | location.reload(); |
| 274 | } else { |
| 275 | alert(response.data.message || 'Action failed'); |
| 276 | $btn.prop('disabled', false); |
| 277 | } |
| 278 | }).fail(function() { |
| 279 | alert('Request failed'); |
| 280 | $btn.prop('disabled', false); |
| 281 | }); |
| 282 | }); |
| 283 | }); |
| 284 | </script> |
| 285 |