@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.
- package/augment-extensions/domain-rules/wordpress/README.md +163 -0
- package/augment-extensions/domain-rules/wordpress/module.json +32 -0
- package/augment-extensions/domain-rules/wordpress/rules/coding-standards.md +617 -0
- package/augment-extensions/domain-rules/wordpress/rules/directory-structure.md +270 -0
- package/augment-extensions/domain-rules/wordpress/rules/file-patterns.md +423 -0
- package/augment-extensions/domain-rules/wordpress/rules/gutenberg-blocks.md +493 -0
- package/augment-extensions/domain-rules/wordpress/rules/performance.md +568 -0
- package/augment-extensions/domain-rules/wordpress/rules/plugin-development.md +510 -0
- package/augment-extensions/domain-rules/wordpress/rules/project-detection.md +251 -0
- package/augment-extensions/domain-rules/wordpress/rules/rest-api.md +501 -0
- package/augment-extensions/domain-rules/wordpress/rules/security.md +564 -0
- package/augment-extensions/domain-rules/wordpress/rules/theme-development.md +388 -0
- package/augment-extensions/domain-rules/wordpress/rules/woocommerce.md +441 -0
- package/augment-extensions/domain-rules/wordpress-plugin/README.md +139 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/ajax-plugin.md +1599 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/custom-post-type-plugin.md +1727 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block-plugin.md +428 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block.md +422 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/mvc-plugin.md +1623 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/object-oriented-plugin.md +1343 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/rest-endpoint.md +734 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/settings-page-plugin.md +1350 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/simple-procedural-plugin.md +503 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/singleton-plugin.md +971 -0
- package/augment-extensions/domain-rules/wordpress-plugin/module.json +53 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/activation-hooks.md +770 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/admin-interface.md +874 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/ajax-handlers.md +629 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/asset-management.md +559 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/context-providers.md +709 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/cron-jobs.md +736 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/database-management.md +1057 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/documentation-standards.md +463 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/frontend-functionality.md +478 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/gutenberg-blocks.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/internationalization.md +416 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/migration.md +667 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/performance-optimization.md +878 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-architecture.md +693 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-structure.md +352 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/rest-api.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/scaffolding-workflow.md +624 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/security-best-practices.md +866 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing-patterns.md +1165 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing.md +414 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/vscode-integration.md +751 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/woocommerce-integration.md +949 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/wordpress-org-submission.md +458 -0
- package/augment-extensions/examples/gutenberg-block-plugin/README.md +101 -0
- package/augment-extensions/examples/gutenberg-block-plugin/examples/testimonial-block.md +428 -0
- package/augment-extensions/examples/gutenberg-block-plugin/module.json +40 -0
- package/augment-extensions/examples/rest-api-plugin/README.md +98 -0
- package/augment-extensions/examples/rest-api-plugin/examples/task-manager-api.md +1299 -0
- package/augment-extensions/examples/rest-api-plugin/module.json +40 -0
- package/augment-extensions/examples/woocommerce-extension/README.md +98 -0
- package/augment-extensions/examples/woocommerce-extension/examples/product-customizer.md +763 -0
- package/augment-extensions/examples/woocommerce-extension/module.json +40 -0
- package/augment-extensions/workflows/wordpress-plugin/README.md +232 -0
- package/augment-extensions/workflows/wordpress-plugin/ai-prompts.md +839 -0
- package/augment-extensions/workflows/wordpress-plugin/bead-decomposition-patterns.md +854 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/complete-plugin-example.md +540 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/custom-post-type-example.md +1083 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/feature-addition-workflow.md +669 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/plugin-creation-workflow.md +597 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/secure-form-handler-example.md +925 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/security-audit-workflow.md +752 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/wordpress-org-submission-workflow.md +773 -0
- package/augment-extensions/workflows/wordpress-plugin/module.json +49 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/best-practices.md +942 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/development-workflow.md +702 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/submission-workflow.md +728 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/testing-workflow.md +775 -0
- package/cli/dist/cli.js +5 -1
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/show.d.ts.map +1 -1
- package/cli/dist/commands/show.js +41 -0
- package/cli/dist/commands/show.js.map +1 -1
- package/modules.md +52 -0
- 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
|
+
|