@mytechtoday/augment-extensions 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/augment-extensions/domain-rules/wordpress/README.md +163 -0
  2. package/augment-extensions/domain-rules/wordpress/module.json +32 -0
  3. package/augment-extensions/domain-rules/wordpress/rules/coding-standards.md +617 -0
  4. package/augment-extensions/domain-rules/wordpress/rules/directory-structure.md +270 -0
  5. package/augment-extensions/domain-rules/wordpress/rules/file-patterns.md +423 -0
  6. package/augment-extensions/domain-rules/wordpress/rules/gutenberg-blocks.md +493 -0
  7. package/augment-extensions/domain-rules/wordpress/rules/performance.md +568 -0
  8. package/augment-extensions/domain-rules/wordpress/rules/plugin-development.md +510 -0
  9. package/augment-extensions/domain-rules/wordpress/rules/project-detection.md +251 -0
  10. package/augment-extensions/domain-rules/wordpress/rules/rest-api.md +501 -0
  11. package/augment-extensions/domain-rules/wordpress/rules/security.md +564 -0
  12. package/augment-extensions/domain-rules/wordpress/rules/theme-development.md +388 -0
  13. package/augment-extensions/domain-rules/wordpress/rules/woocommerce.md +441 -0
  14. package/augment-extensions/domain-rules/wordpress-plugin/README.md +139 -0
  15. package/augment-extensions/domain-rules/wordpress-plugin/examples/ajax-plugin.md +1599 -0
  16. package/augment-extensions/domain-rules/wordpress-plugin/examples/custom-post-type-plugin.md +1727 -0
  17. package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block-plugin.md +428 -0
  18. package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block.md +422 -0
  19. package/augment-extensions/domain-rules/wordpress-plugin/examples/mvc-plugin.md +1623 -0
  20. package/augment-extensions/domain-rules/wordpress-plugin/examples/object-oriented-plugin.md +1343 -0
  21. package/augment-extensions/domain-rules/wordpress-plugin/examples/rest-endpoint.md +734 -0
  22. package/augment-extensions/domain-rules/wordpress-plugin/examples/settings-page-plugin.md +1350 -0
  23. package/augment-extensions/domain-rules/wordpress-plugin/examples/simple-procedural-plugin.md +503 -0
  24. package/augment-extensions/domain-rules/wordpress-plugin/examples/singleton-plugin.md +971 -0
  25. package/augment-extensions/domain-rules/wordpress-plugin/module.json +53 -0
  26. package/augment-extensions/domain-rules/wordpress-plugin/rules/activation-hooks.md +770 -0
  27. package/augment-extensions/domain-rules/wordpress-plugin/rules/admin-interface.md +874 -0
  28. package/augment-extensions/domain-rules/wordpress-plugin/rules/ajax-handlers.md +629 -0
  29. package/augment-extensions/domain-rules/wordpress-plugin/rules/asset-management.md +559 -0
  30. package/augment-extensions/domain-rules/wordpress-plugin/rules/context-providers.md +709 -0
  31. package/augment-extensions/domain-rules/wordpress-plugin/rules/cron-jobs.md +736 -0
  32. package/augment-extensions/domain-rules/wordpress-plugin/rules/database-management.md +1057 -0
  33. package/augment-extensions/domain-rules/wordpress-plugin/rules/documentation-standards.md +463 -0
  34. package/augment-extensions/domain-rules/wordpress-plugin/rules/frontend-functionality.md +478 -0
  35. package/augment-extensions/domain-rules/wordpress-plugin/rules/gutenberg-blocks.md +818 -0
  36. package/augment-extensions/domain-rules/wordpress-plugin/rules/internationalization.md +416 -0
  37. package/augment-extensions/domain-rules/wordpress-plugin/rules/migration.md +667 -0
  38. package/augment-extensions/domain-rules/wordpress-plugin/rules/performance-optimization.md +878 -0
  39. package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-architecture.md +693 -0
  40. package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-structure.md +352 -0
  41. package/augment-extensions/domain-rules/wordpress-plugin/rules/rest-api.md +818 -0
  42. package/augment-extensions/domain-rules/wordpress-plugin/rules/scaffolding-workflow.md +624 -0
  43. package/augment-extensions/domain-rules/wordpress-plugin/rules/security-best-practices.md +866 -0
  44. package/augment-extensions/domain-rules/wordpress-plugin/rules/testing-patterns.md +1165 -0
  45. package/augment-extensions/domain-rules/wordpress-plugin/rules/testing.md +414 -0
  46. package/augment-extensions/domain-rules/wordpress-plugin/rules/vscode-integration.md +751 -0
  47. package/augment-extensions/domain-rules/wordpress-plugin/rules/woocommerce-integration.md +949 -0
  48. package/augment-extensions/domain-rules/wordpress-plugin/rules/wordpress-org-submission.md +458 -0
  49. package/augment-extensions/examples/gutenberg-block-plugin/README.md +101 -0
  50. package/augment-extensions/examples/gutenberg-block-plugin/examples/testimonial-block.md +428 -0
  51. package/augment-extensions/examples/gutenberg-block-plugin/module.json +40 -0
  52. package/augment-extensions/examples/rest-api-plugin/README.md +98 -0
  53. package/augment-extensions/examples/rest-api-plugin/examples/task-manager-api.md +1299 -0
  54. package/augment-extensions/examples/rest-api-plugin/module.json +40 -0
  55. package/augment-extensions/examples/woocommerce-extension/README.md +98 -0
  56. package/augment-extensions/examples/woocommerce-extension/examples/product-customizer.md +763 -0
  57. package/augment-extensions/examples/woocommerce-extension/module.json +40 -0
  58. package/augment-extensions/workflows/wordpress-plugin/README.md +232 -0
  59. package/augment-extensions/workflows/wordpress-plugin/ai-prompts.md +839 -0
  60. package/augment-extensions/workflows/wordpress-plugin/bead-decomposition-patterns.md +854 -0
  61. package/augment-extensions/workflows/wordpress-plugin/examples/complete-plugin-example.md +540 -0
  62. package/augment-extensions/workflows/wordpress-plugin/examples/custom-post-type-example.md +1083 -0
  63. package/augment-extensions/workflows/wordpress-plugin/examples/feature-addition-workflow.md +669 -0
  64. package/augment-extensions/workflows/wordpress-plugin/examples/plugin-creation-workflow.md +597 -0
  65. package/augment-extensions/workflows/wordpress-plugin/examples/secure-form-handler-example.md +925 -0
  66. package/augment-extensions/workflows/wordpress-plugin/examples/security-audit-workflow.md +752 -0
  67. package/augment-extensions/workflows/wordpress-plugin/examples/wordpress-org-submission-workflow.md +773 -0
  68. package/augment-extensions/workflows/wordpress-plugin/module.json +49 -0
  69. package/augment-extensions/workflows/wordpress-plugin/rules/best-practices.md +942 -0
  70. package/augment-extensions/workflows/wordpress-plugin/rules/development-workflow.md +702 -0
  71. package/augment-extensions/workflows/wordpress-plugin/rules/submission-workflow.md +728 -0
  72. package/augment-extensions/workflows/wordpress-plugin/rules/testing-workflow.md +775 -0
  73. package/cli/dist/cli.js +5 -1
  74. package/cli/dist/cli.js.map +1 -1
  75. package/cli/dist/commands/show.d.ts.map +1 -1
  76. package/cli/dist/commands/show.js +41 -0
  77. package/cli/dist/commands/show.js.map +1 -1
  78. package/modules.md +52 -0
  79. package/package.json +1 -1
@@ -0,0 +1,736 @@
1
+ # Cron Jobs and Scheduled Tasks
2
+
3
+ ## Overview
4
+
5
+ This guide covers WordPress cron job implementation for scheduled tasks including wp_schedule_event, custom cron schedules, wp_next_scheduled, wp_unschedule_event, and wp_clear_scheduled_hook.
6
+
7
+ ---
8
+
9
+ ## Basic Cron Job Setup
10
+
11
+ ### Scheduling a Recurring Event
12
+
13
+ ```php
14
+ <?php
15
+ /**
16
+ * Schedule cron job on plugin activation
17
+ */
18
+ function my_plugin_activate() {
19
+ if ( ! wp_next_scheduled( 'my_plugin_daily_task' ) ) {
20
+ wp_schedule_event( time(), 'daily', 'my_plugin_daily_task' );
21
+ }
22
+ }
23
+ register_activation_hook( __FILE__, 'my_plugin_activate' );
24
+
25
+ /**
26
+ * Cron job callback
27
+ */
28
+ function my_plugin_daily_task_callback() {
29
+ // Task code here
30
+ error_log( 'Daily task executed at ' . current_time( 'mysql' ) );
31
+
32
+ // Example: Clean up old data
33
+ global $wpdb;
34
+ $wpdb->query(
35
+ $wpdb->prepare(
36
+ "DELETE FROM {$wpdb->prefix}my_plugin_data
37
+ WHERE created_at < %s
38
+ LIMIT 100",
39
+ date( 'Y-m-d H:i:s', strtotime( '-30 days' ) )
40
+ )
41
+ );
42
+ }
43
+ add_action( 'my_plugin_daily_task', 'my_plugin_daily_task_callback' );
44
+ ```
45
+
46
+ ### Scheduling a Single Event
47
+
48
+ ```php
49
+ <?php
50
+ /**
51
+ * Schedule one-time event
52
+ */
53
+ function my_plugin_schedule_single_event() {
54
+ // Schedule event to run in 1 hour
55
+ wp_schedule_single_event( time() + HOUR_IN_SECONDS, 'my_plugin_single_task' );
56
+ }
57
+
58
+ /**
59
+ * Single event callback
60
+ */
61
+ function my_plugin_single_task_callback() {
62
+ // One-time task code
63
+ update_option( 'my_plugin_task_completed', true );
64
+ }
65
+ add_action( 'my_plugin_single_task', 'my_plugin_single_task_callback' );
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Built-in Cron Schedules
71
+
72
+ WordPress provides these default schedules:
73
+
74
+ - `hourly` - Once per hour
75
+ - `twicedaily` - Twice per day
76
+ - `daily` - Once per day
77
+ - `weekly` - Once per week
78
+
79
+ ```php
80
+ <?php
81
+ // Hourly task
82
+ wp_schedule_event( time(), 'hourly', 'my_plugin_hourly_task' );
83
+
84
+ // Twice daily task
85
+ wp_schedule_event( time(), 'twicedaily', 'my_plugin_twicedaily_task' );
86
+
87
+ // Daily task
88
+ wp_schedule_event( time(), 'daily', 'my_plugin_daily_task' );
89
+
90
+ // Weekly task
91
+ wp_schedule_event( time(), 'weekly', 'my_plugin_weekly_task' );
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Custom Cron Schedules
97
+
98
+ ### Adding Custom Intervals
99
+
100
+ ```php
101
+ <?php
102
+ /**
103
+ * Add custom cron schedules
104
+ */
105
+ function my_plugin_custom_cron_schedules( $schedules ) {
106
+ // Every 5 minutes
107
+ $schedules['every_five_minutes'] = array(
108
+ 'interval' => 5 * MINUTE_IN_SECONDS,
109
+ 'display' => __( 'Every 5 Minutes', 'my-plugin' ),
110
+ );
111
+
112
+ // Every 15 minutes
113
+ $schedules['every_fifteen_minutes'] = array(
114
+ 'interval' => 15 * MINUTE_IN_SECONDS,
115
+ 'display' => __( 'Every 15 Minutes', 'my-plugin' ),
116
+ );
117
+
118
+ // Every 30 minutes
119
+ $schedules['every_thirty_minutes'] = array(
120
+ 'interval' => 30 * MINUTE_IN_SECONDS,
121
+ 'display' => __( 'Every 30 Minutes', 'my-plugin' ),
122
+ );
123
+
124
+ // Every 6 hours
125
+ $schedules['every_six_hours'] = array(
126
+ 'interval' => 6 * HOUR_IN_SECONDS,
127
+ 'display' => __( 'Every 6 Hours', 'my-plugin' ),
128
+ );
129
+
130
+ // Monthly (30 days)
131
+ $schedules['monthly'] = array(
132
+ 'interval' => 30 * DAY_IN_SECONDS,
133
+ 'display' => __( 'Once Monthly', 'my-plugin' ),
134
+ );
135
+
136
+ return $schedules;
137
+ }
138
+ add_filter( 'cron_schedules', 'my_plugin_custom_cron_schedules' );
139
+
140
+ /**
141
+ * Schedule custom interval task
142
+ */
143
+ function my_plugin_schedule_custom_task() {
144
+ if ( ! wp_next_scheduled( 'my_plugin_custom_task' ) ) {
145
+ wp_schedule_event( time(), 'every_five_minutes', 'my_plugin_custom_task' );
146
+ }
147
+ }
148
+ add_action( 'wp', 'my_plugin_schedule_custom_task' );
149
+
150
+ /**
151
+ * Custom task callback
152
+ */
153
+ function my_plugin_custom_task_callback() {
154
+ // Task code here
155
+ }
156
+ add_action( 'my_plugin_custom_task', 'my_plugin_custom_task_callback' );
157
+ ```
158
+
159
+ ---
160
+
161
+ ## Managing Scheduled Events
162
+
163
+ ### Check if Event is Scheduled
164
+
165
+ ```php
166
+ <?php
167
+ /**
168
+ * Check if event is already scheduled
169
+ */
170
+ $timestamp = wp_next_scheduled( 'my_plugin_daily_task' );
171
+
172
+ if ( $timestamp ) {
173
+ echo 'Next run: ' . date( 'Y-m-d H:i:s', $timestamp );
174
+ } else {
175
+ echo 'Not scheduled';
176
+ }
177
+ ```
178
+
179
+ ### Unschedule a Specific Event
180
+
181
+ ```php
182
+ <?php
183
+ /**
184
+ * Unschedule specific event
185
+ */
186
+ $timestamp = wp_next_scheduled( 'my_plugin_daily_task' );
187
+
188
+ if ( $timestamp ) {
189
+ wp_unschedule_event( $timestamp, 'my_plugin_daily_task' );
190
+ }
191
+ ```
192
+
193
+ ### Clear All Instances of a Hook
194
+
195
+ ```php
196
+ <?php
197
+ /**
198
+ * Clear all scheduled instances of a hook
199
+ */
200
+ wp_clear_scheduled_hook( 'my_plugin_daily_task' );
201
+ ```
202
+
203
+ ### Reschedule an Event
204
+
205
+ ```php
206
+ <?php
207
+ /**
208
+ * Reschedule event with new interval
209
+ */
210
+ function my_plugin_reschedule_task() {
211
+ // Clear existing schedule
212
+ wp_clear_scheduled_hook( 'my_plugin_task' );
213
+
214
+ // Schedule with new interval
215
+ if ( ! wp_next_scheduled( 'my_plugin_task' ) ) {
216
+ wp_schedule_event( time(), 'hourly', 'my_plugin_task' );
217
+ }
218
+ }
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Deactivation and Uninstall
224
+
225
+ ### Clear Cron Jobs on Deactivation
226
+
227
+ ```php
228
+ <?php
229
+ /**
230
+ * Clear cron jobs on plugin deactivation
231
+ */
232
+ function my_plugin_deactivate() {
233
+ // Clear all scheduled hooks
234
+ wp_clear_scheduled_hook( 'my_plugin_daily_task' );
235
+ wp_clear_scheduled_hook( 'my_plugin_hourly_task' );
236
+ wp_clear_scheduled_hook( 'my_plugin_custom_task' );
237
+ }
238
+ register_deactivation_hook( __FILE__, 'my_plugin_deactivate' );
239
+ ```
240
+
241
+ ### Clear Cron Jobs on Uninstall
242
+
243
+ ```php
244
+ <?php
245
+ /**
246
+ * uninstall.php
247
+ */
248
+ if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
249
+ exit;
250
+ }
251
+
252
+ // Clear all scheduled hooks
253
+ wp_clear_scheduled_hook( 'my_plugin_daily_task' );
254
+ wp_clear_scheduled_hook( 'my_plugin_hourly_task' );
255
+ wp_clear_scheduled_hook( 'my_plugin_custom_task' );
256
+ ```
257
+
258
+ ---
259
+
260
+ ## Advanced Patterns
261
+
262
+ ### Cron Job with Arguments
263
+
264
+ ```php
265
+ <?php
266
+ /**
267
+ * Schedule event with arguments
268
+ */
269
+ function my_plugin_schedule_task_with_args( $user_id ) {
270
+ $args = array( $user_id );
271
+
272
+ if ( ! wp_next_scheduled( 'my_plugin_user_task', $args ) ) {
273
+ wp_schedule_single_event( time() + HOUR_IN_SECONDS, 'my_plugin_user_task', $args );
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Callback with arguments
279
+ */
280
+ function my_plugin_user_task_callback( $user_id ) {
281
+ // Process user-specific task
282
+ $user = get_user_by( 'id', $user_id );
283
+
284
+ if ( $user ) {
285
+ // Send email, update data, etc.
286
+ wp_mail(
287
+ $user->user_email,
288
+ 'Scheduled Task',
289
+ 'Your scheduled task has been completed.'
290
+ );
291
+ }
292
+ }
293
+ add_action( 'my_plugin_user_task', 'my_plugin_user_task_callback' );
294
+ ```
295
+
296
+ ### Batch Processing with Cron
297
+
298
+ ```php
299
+ <?php
300
+ /**
301
+ * Process items in batches
302
+ */
303
+ function my_plugin_batch_process_callback() {
304
+ global $wpdb;
305
+
306
+ $table_name = $wpdb->prefix . 'my_plugin_queue';
307
+
308
+ // Get batch of unprocessed items
309
+ $items = $wpdb->get_results(
310
+ "SELECT * FROM $table_name
311
+ WHERE status = 'pending'
312
+ ORDER BY created_at ASC
313
+ LIMIT 50"
314
+ );
315
+
316
+ foreach ( $items as $item ) {
317
+ // Process item
318
+ $result = my_plugin_process_item( $item );
319
+
320
+ // Update status
321
+ $wpdb->update(
322
+ $table_name,
323
+ array( 'status' => $result ? 'completed' : 'failed' ),
324
+ array( 'id' => $item->id ),
325
+ array( '%s' ),
326
+ array( '%d' )
327
+ );
328
+ }
329
+
330
+ // Log batch completion
331
+ error_log( sprintf( 'Processed %d items', count( $items ) ) );
332
+ }
333
+ add_action( 'my_plugin_batch_process', 'my_plugin_batch_process_callback' );
334
+ ```
335
+
336
+ ### Conditional Cron Execution
337
+
338
+ ```php
339
+ <?php
340
+ /**
341
+ * Execute cron only under certain conditions
342
+ */
343
+ function my_plugin_conditional_task_callback() {
344
+ // Check if task should run
345
+ $should_run = get_option( 'my_plugin_task_enabled', true );
346
+
347
+ if ( ! $should_run ) {
348
+ error_log( 'Task skipped: disabled in settings' );
349
+ return;
350
+ }
351
+
352
+ // Check time window (e.g., only run during off-peak hours)
353
+ $current_hour = (int) current_time( 'H' );
354
+
355
+ if ( $current_hour >= 9 && $current_hour <= 17 ) {
356
+ error_log( 'Task skipped: peak hours' );
357
+ return;
358
+ }
359
+
360
+ // Execute task
361
+ my_plugin_execute_task();
362
+ }
363
+ add_action( 'my_plugin_conditional_task', 'my_plugin_conditional_task_callback' );
364
+ ```
365
+
366
+ ### Cron Job with Error Handling
367
+
368
+ ```php
369
+ <?php
370
+ /**
371
+ * Cron job with comprehensive error handling
372
+ */
373
+ function my_plugin_safe_cron_callback() {
374
+ try {
375
+ // Set time limit
376
+ set_time_limit( 300 ); // 5 minutes
377
+
378
+ // Execute task
379
+ $result = my_plugin_execute_task();
380
+
381
+ if ( is_wp_error( $result ) ) {
382
+ throw new Exception( $result->get_error_message() );
383
+ }
384
+
385
+ // Log success
386
+ error_log( 'Cron task completed successfully' );
387
+ update_option( 'my_plugin_last_cron_run', current_time( 'mysql' ) );
388
+
389
+ } catch ( Exception $e ) {
390
+ // Log error
391
+ error_log( 'Cron task failed: ' . $e->getMessage() );
392
+
393
+ // Send admin notification
394
+ wp_mail(
395
+ get_option( 'admin_email' ),
396
+ 'Cron Task Failed',
397
+ 'Error: ' . $e->getMessage()
398
+ );
399
+
400
+ // Update error count
401
+ $error_count = (int) get_option( 'my_plugin_cron_errors', 0 );
402
+ update_option( 'my_plugin_cron_errors', $error_count + 1 );
403
+ }
404
+ }
405
+ add_action( 'my_plugin_safe_cron', 'my_plugin_safe_cron_callback' );
406
+ ```
407
+
408
+ ---
409
+
410
+ ## Best Practices
411
+
412
+ ### Performance
413
+
414
+ 1. **Limit batch size**: Process items in small batches to avoid timeouts
415
+ 2. **Set time limits**: Use `set_time_limit()` for long-running tasks
416
+ 3. **Use LIMIT in queries**: Don't fetch all records at once
417
+ 4. **Log execution**: Track when tasks run and how long they take
418
+ 5. **Avoid peak hours**: Schedule intensive tasks during off-peak times
419
+
420
+ ```php
421
+ <?php
422
+ // Good - Process in batches
423
+ function my_plugin_efficient_cron() {
424
+ global $wpdb;
425
+
426
+ $batch_size = 50;
427
+ $processed = 0;
428
+
429
+ $items = $wpdb->get_results(
430
+ $wpdb->prepare(
431
+ "SELECT * FROM {$wpdb->prefix}my_plugin_data
432
+ WHERE status = 'pending'
433
+ LIMIT %d",
434
+ $batch_size
435
+ )
436
+ );
437
+
438
+ foreach ( $items as $item ) {
439
+ my_plugin_process_item( $item );
440
+ $processed++;
441
+ }
442
+
443
+ error_log( "Processed $processed items" );
444
+ }
445
+ ```
446
+
447
+ ### Reliability
448
+
449
+ 1. **Check if scheduled**: Always check `wp_next_scheduled()` before scheduling
450
+ 2. **Clear on deactivation**: Remove scheduled events when plugin is deactivated
451
+ 3. **Handle errors**: Use try-catch blocks and log errors
452
+ 4. **Verify execution**: Log when tasks run successfully
453
+ 5. **Monitor failures**: Track and alert on repeated failures
454
+
455
+ ```php
456
+ <?php
457
+ // Good - Check before scheduling
458
+ function my_plugin_ensure_cron_scheduled() {
459
+ if ( ! wp_next_scheduled( 'my_plugin_task' ) ) {
460
+ wp_schedule_event( time(), 'daily', 'my_plugin_task' );
461
+ }
462
+ }
463
+ add_action( 'wp', 'my_plugin_ensure_cron_scheduled' );
464
+ ```
465
+
466
+ ### Security
467
+
468
+ 1. **Validate data**: Sanitize and validate all data in cron callbacks
469
+ 2. **Check capabilities**: Verify permissions if needed
470
+ 3. **Use nonces**: For user-triggered scheduled events
471
+ 4. **Limit access**: Don't expose cron URLs publicly
472
+ 5. **Log suspicious activity**: Monitor for unusual patterns
473
+
474
+ ```php
475
+ <?php
476
+ // Good - Validate data in cron callback
477
+ function my_plugin_secure_cron_callback() {
478
+ global $wpdb;
479
+
480
+ $items = $wpdb->get_results(
481
+ "SELECT * FROM {$wpdb->prefix}my_plugin_data
482
+ WHERE status = 'pending'
483
+ LIMIT 50"
484
+ );
485
+
486
+ foreach ( $items as $item ) {
487
+ // Validate data before processing
488
+ $email = sanitize_email( $item->email );
489
+ $user_id = absint( $item->user_id );
490
+
491
+ if ( ! is_email( $email ) || ! $user_id ) {
492
+ error_log( "Invalid data in cron: item ID {$item->id}" );
493
+ continue;
494
+ }
495
+
496
+ // Process validated data
497
+ my_plugin_send_email( $email, $user_id );
498
+ }
499
+ }
500
+ ```
501
+
502
+ ---
503
+
504
+ ## Debugging Cron Jobs
505
+
506
+ ### View Scheduled Events
507
+
508
+ ```php
509
+ <?php
510
+ /**
511
+ * Display all scheduled cron events (admin page)
512
+ */
513
+ function my_plugin_display_cron_events() {
514
+ if ( ! current_user_can( 'manage_options' ) ) {
515
+ return;
516
+ }
517
+
518
+ $cron_array = _get_cron_array();
519
+
520
+ echo '<h2>Scheduled Events</h2>';
521
+ echo '<table>';
522
+ echo '<tr><th>Hook</th><th>Next Run</th><th>Schedule</th></tr>';
523
+
524
+ foreach ( $cron_array as $timestamp => $cron ) {
525
+ foreach ( $cron as $hook => $events ) {
526
+ foreach ( $events as $key => $event ) {
527
+ echo '<tr>';
528
+ echo '<td>' . esc_html( $hook ) . '</td>';
529
+ echo '<td>' . date( 'Y-m-d H:i:s', $timestamp ) . '</td>';
530
+ echo '<td>' . ( isset( $event['schedule'] ) ? esc_html( $event['schedule'] ) : 'Single' ) . '</td>';
531
+ echo '</tr>';
532
+ }
533
+ }
534
+ }
535
+
536
+ echo '</table>';
537
+ }
538
+ ```
539
+
540
+ ### Test Cron Job Manually
541
+
542
+ ```php
543
+ <?php
544
+ /**
545
+ * Manually trigger cron job for testing
546
+ */
547
+ function my_plugin_test_cron() {
548
+ if ( ! current_user_can( 'manage_options' ) ) {
549
+ wp_die( 'Unauthorized' );
550
+ }
551
+
552
+ // Trigger the cron callback directly
553
+ do_action( 'my_plugin_daily_task' );
554
+
555
+ echo 'Cron job executed manually';
556
+ }
557
+
558
+ // Add admin menu item for testing
559
+ add_action( 'admin_menu', function() {
560
+ add_submenu_page(
561
+ 'tools.php',
562
+ 'Test Cron',
563
+ 'Test Cron',
564
+ 'manage_options',
565
+ 'test-cron',
566
+ 'my_plugin_test_cron'
567
+ );
568
+ } );
569
+ ```
570
+
571
+ ### Enable WP-Cron Debugging
572
+
573
+ ```php
574
+ <?php
575
+ /**
576
+ * wp-config.php
577
+ */
578
+ define( 'WP_DEBUG', true );
579
+ define( 'WP_DEBUG_LOG', true );
580
+
581
+ /**
582
+ * Log cron execution
583
+ */
584
+ function my_plugin_log_cron_execution() {
585
+ error_log( 'Cron executed: ' . current_action() );
586
+ }
587
+ add_action( 'my_plugin_daily_task', 'my_plugin_log_cron_execution', 1 );
588
+ ```
589
+
590
+ ---
591
+
592
+ ## Alternative: System Cron
593
+
594
+ For better reliability, use system cron instead of WP-Cron:
595
+
596
+ ### Disable WP-Cron
597
+
598
+ ```php
599
+ <?php
600
+ /**
601
+ * wp-config.php
602
+ */
603
+ define( 'DISABLE_WP_CRON', true );
604
+ ```
605
+
606
+ ### Setup System Cron
607
+
608
+ ```bash
609
+ # Edit crontab
610
+ crontab -e
611
+
612
+ # Add line to run WP-Cron every 5 minutes
613
+ */5 * * * * wget -q -O - https://example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
614
+
615
+ # Or using curl
616
+ */5 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
617
+
618
+ # Or using WP-CLI
619
+ */5 * * * * cd /path/to/wordpress && wp cron event run --due-now >/dev/null 2>&1
620
+ ```
621
+
622
+ ---
623
+
624
+ ## Common Pitfalls
625
+
626
+ ### ❌ DON'T
627
+
628
+ ```php
629
+ <?php
630
+ // Don't schedule without checking
631
+ wp_schedule_event( time(), 'daily', 'my_task' ); // WRONG - Creates duplicates
632
+
633
+ // Don't forget to clear on deactivation
634
+ function my_plugin_deactivate() {
635
+ // Missing: wp_clear_scheduled_hook( 'my_task' );
636
+ } // WRONG
637
+
638
+ // Don't use infinite loops
639
+ function my_bad_cron_callback() {
640
+ while ( true ) {
641
+ // Process items
642
+ }
643
+ } // WRONG - Will timeout
644
+
645
+ // Don't process all items at once
646
+ function my_bad_batch_process() {
647
+ $items = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}items" ); // WRONG - No LIMIT
648
+ foreach ( $items as $item ) {
649
+ process_item( $item );
650
+ }
651
+ }
652
+
653
+ // Don't ignore errors
654
+ function my_bad_error_handling() {
655
+ my_risky_operation(); // WRONG - No error handling
656
+ }
657
+
658
+ // Don't hardcode timestamps
659
+ wp_schedule_event( 1234567890, 'daily', 'my_task' ); // WRONG - Use time()
660
+ ```
661
+
662
+ ### ✅ DO
663
+
664
+ ```php
665
+ <?php
666
+ // Always check before scheduling
667
+ if ( ! wp_next_scheduled( 'my_task' ) ) {
668
+ wp_schedule_event( time(), 'daily', 'my_task' );
669
+ } // CORRECT
670
+
671
+ // Clear on deactivation
672
+ function my_plugin_deactivate() {
673
+ wp_clear_scheduled_hook( 'my_task' );
674
+ } // CORRECT
675
+ register_deactivation_hook( __FILE__, 'my_plugin_deactivate' );
676
+
677
+ // Process in batches
678
+ function my_good_batch_process() {
679
+ global $wpdb;
680
+
681
+ $items = $wpdb->get_results(
682
+ "SELECT * FROM {$wpdb->prefix}items
683
+ WHERE status = 'pending'
684
+ LIMIT 50"
685
+ ); // CORRECT - Limited batch
686
+
687
+ foreach ( $items as $item ) {
688
+ process_item( $item );
689
+ }
690
+ }
691
+
692
+ // Handle errors
693
+ function my_good_error_handling() {
694
+ try {
695
+ my_risky_operation();
696
+ } catch ( Exception $e ) {
697
+ error_log( 'Cron error: ' . $e->getMessage() );
698
+ }
699
+ } // CORRECT
700
+
701
+ // Use time() for current timestamp
702
+ wp_schedule_event( time(), 'daily', 'my_task' ); // CORRECT
703
+ ```
704
+
705
+ ---
706
+
707
+ ## Summary
708
+
709
+ **Key Takeaways:**
710
+
711
+ 1. **Scheduling**: Use `wp_schedule_event()` for recurring tasks, `wp_schedule_single_event()` for one-time tasks
712
+ 2. **Custom intervals**: Add custom schedules with `cron_schedules` filter
713
+ 3. **Check before scheduling**: Always use `wp_next_scheduled()` to avoid duplicates
714
+ 4. **Unscheduling**: Use `wp_unschedule_event()` for specific events, `wp_clear_scheduled_hook()` for all instances
715
+ 5. **Deactivation**: Clear all scheduled hooks on plugin deactivation
716
+ 6. **Batch processing**: Process items in small batches to avoid timeouts
717
+ 7. **Error handling**: Use try-catch blocks and log errors
718
+ 8. **Debugging**: Test cron jobs manually and monitor execution
719
+ 9. **System cron**: Consider using system cron for better reliability
720
+
721
+ **Common Mistakes to Avoid:**
722
+
723
+ - Scheduling without checking for existing events
724
+ - Forgetting to clear scheduled hooks on deactivation
725
+ - Processing too many items at once
726
+ - Ignoring errors and timeouts
727
+ - Not logging execution for debugging
728
+ - Using hardcoded timestamps instead of `time()`
729
+
730
+ **Resources:**
731
+
732
+ - [WordPress Cron API](https://developer.wordpress.org/plugins/cron/)
733
+ - [wp_schedule_event()](https://developer.wordpress.org/reference/functions/wp_schedule_event/)
734
+ - [wp_next_scheduled()](https://developer.wordpress.org/reference/functions/wp_next_scheduled/)
735
+ - [wp_clear_scheduled_hook()](https://developer.wordpress.org/reference/functions/wp_clear_scheduled_hook/)
736
+