@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,942 @@
1
+ # WordPress Plugin Development Best Practices
2
+
3
+ ## Overview
4
+
5
+ This document provides comprehensive best practices for WordPress plugin development, covering code organization, naming conventions, security, performance, accessibility, and backward compatibility.
6
+
7
+ ## Code Organization
8
+
9
+ ### Directory Structure
10
+
11
+ **Standard Plugin Structure**:
12
+
13
+ ```
14
+ plugin-name/
15
+ ├── plugin-name.php # Main plugin file
16
+ ├── uninstall.php # Uninstall cleanup
17
+ ├── readme.txt # WordPress.org readme
18
+ ├── LICENSE # License file
19
+ ├── includes/ # Core plugin classes
20
+ │ ├── class-plugin-name.php
21
+ │ ├── class-activator.php
22
+ │ ├── class-deactivator.php
23
+ │ └── class-loader.php
24
+ ├── admin/ # Admin-specific functionality
25
+ │ ├── class-admin.php
26
+ │ ├── partials/ # Admin view templates
27
+ │ ├── css/
28
+ │ └── js/
29
+ ├── public/ # Public-facing functionality
30
+ │ ├── class-public.php
31
+ │ ├── partials/ # Public view templates
32
+ │ ├── css/
33
+ │ └── js/
34
+ ├── languages/ # Translation files
35
+ ├── assets/ # Plugin assets for WordPress.org
36
+ │ ├── banner-772x250.png
37
+ │ ├── banner-1544x500.png
38
+ │ ├── icon-128x128.png
39
+ │ └── icon-256x256.png
40
+ └── tests/ # PHPUnit tests
41
+ ├── bootstrap.php
42
+ ├── unit/
43
+ └── integration/
44
+ ```
45
+
46
+ ### File Organization Best Practices
47
+
48
+ **DO**:
49
+ - ✅ One class per file
50
+ - ✅ Group related functionality in subdirectories
51
+ - ✅ Separate admin and public functionality
52
+ - ✅ Keep templates in `partials/` directories
53
+ - ✅ Organize assets by type (css, js, images)
54
+
55
+ **DON'T**:
56
+ - ❌ Mix multiple classes in one file
57
+ - ❌ Put all code in main plugin file
58
+ - ❌ Mix admin and public code
59
+ - ❌ Hardcode HTML in PHP classes
60
+ - ❌ Put assets in root directory
61
+
62
+ ## Naming Conventions
63
+
64
+ ### File Naming
65
+
66
+ **PHP Files**:
67
+ ```
68
+ class-plugin-name.php # Class files (lowercase, hyphens)
69
+ class-admin.php
70
+ class-public.php
71
+ plugin-name-functions.php # Function files
72
+ ```
73
+
74
+ **Template Files**:
75
+ ```
76
+ admin-display.php # Admin templates
77
+ public-display.php # Public templates
78
+ settings-page.php
79
+ ```
80
+
81
+ **Asset Files**:
82
+ ```
83
+ plugin-name-admin.css # Prefixed with plugin name
84
+ plugin-name-public.js
85
+ plugin-name-icon.png
86
+ ```
87
+
88
+ ### Code Naming
89
+
90
+ **Classes**:
91
+ ```php
92
+ class Plugin_Name {} # Capitalized with underscores
93
+ class Plugin_Name_Admin {}
94
+ class Plugin_Name_Public {}
95
+ ```
96
+
97
+ **Functions**:
98
+ ```php
99
+ function plugin_name_activate() {} # Lowercase with underscores
100
+ function plugin_name_get_data() {}
101
+ function plugin_name_sanitize_input() {}
102
+ ```
103
+
104
+ **Variables**:
105
+ ```php
106
+ $plugin_name = 'value'; # Lowercase with underscores
107
+ $user_data = array();
108
+ $is_active = true;
109
+ ```
110
+
111
+ **Constants**:
112
+ ```php
113
+ define( 'PLUGIN_NAME_VERSION', '1.0.0' ); # Uppercase with underscores
114
+ define( 'PLUGIN_NAME_PATH', plugin_dir_path( __FILE__ ) );
115
+ ```
116
+
117
+ **Hooks**:
118
+ ```php
119
+ // Actions
120
+ do_action( 'plugin_name_before_save' );
121
+ do_action( 'plugin_name_after_save' );
122
+
123
+ // Filters
124
+ apply_filters( 'plugin_name_data', $data );
125
+ apply_filters( 'plugin_name_settings', $settings );
126
+ ```
127
+
128
+ ### Database Naming
129
+
130
+ **Tables**:
131
+ ```php
132
+ global $wpdb;
133
+ $table_name = $wpdb->prefix . 'plugin_name_items'; # Prefixed, lowercase, underscores
134
+ ```
135
+
136
+ **Options**:
137
+ ```php
138
+ get_option( 'plugin_name_settings' ); # Prefixed with plugin name
139
+ get_option( 'plugin_name_version' );
140
+ ```
141
+
142
+ **Post Meta**:
143
+ ```php
144
+ get_post_meta( $post_id, '_plugin_name_meta_key', true ); # Prefixed, leading underscore for hidden
145
+ ```
146
+
147
+ **User Meta**:
148
+ ```php
149
+ get_user_meta( $user_id, 'plugin_name_preference', true );
150
+ ```
151
+
152
+ **Transients**:
153
+ ```php
154
+ get_transient( 'plugin_name_cache_key' ); # Prefixed, max 172 characters
155
+ ```
156
+
157
+ ## WordPress Coding Standards
158
+
159
+ ### Indentation and Spacing
160
+
161
+ **Use Tabs for Indentation**:
162
+ ```php
163
+ function plugin_name_example() {
164
+ if ( $condition ) {
165
+ // Code here (indented with tab)
166
+ }
167
+ }
168
+ ```
169
+
170
+ **Space After Control Structures**:
171
+ ```php
172
+ if ( $condition ) { // Space after 'if', space inside parentheses
173
+ // Code
174
+ }
175
+
176
+ foreach ( $items as $item ) { // Space after 'foreach'
177
+ // Code
178
+ }
179
+ ```
180
+
181
+ **No Space Before Function Parentheses**:
182
+ ```php
183
+ function my_function( $param ) { // No space before (
184
+ // Code
185
+ }
186
+ ```
187
+
188
+ ### Braces and Brackets
189
+
190
+ **Opening Braces on Same Line**:
191
+ ```php
192
+ if ( $condition ) {
193
+ // Code
194
+ }
195
+
196
+ function my_function() {
197
+ // Code
198
+ }
199
+ ```
200
+
201
+ **Arrays**:
202
+ ```php
203
+ $array = array(
204
+ 'key1' => 'value1',
205
+ 'key2' => 'value2',
206
+ );
207
+ ```
208
+
209
+ ### Quotes
210
+
211
+ **Use Single Quotes for Strings**:
212
+ ```php
213
+ $string = 'Hello World';
214
+ $html = '<div class="wrapper">'; // Single quotes for HTML
215
+ ```
216
+
217
+ **Use Double Quotes for Interpolation**:
218
+ ```php
219
+ $name = 'John';
220
+ $greeting = "Hello, $name"; // Double quotes for variable interpolation
221
+ ```
222
+
223
+ ### Yoda Conditions
224
+
225
+ **Use Yoda Conditions for Comparisons**:
226
+ ```php
227
+ if ( 'value' === $variable ) { // Constant on left
228
+ // Code
229
+ }
230
+
231
+ if ( true === $is_active ) {
232
+ // Code
233
+ }
234
+ ```
235
+
236
+ ## Security Checklist
237
+
238
+ ### Input Validation and Sanitization
239
+
240
+ **Always Sanitize User Input**:
241
+
242
+ ```php
243
+ // Text fields
244
+ $text = sanitize_text_field( $_POST['text'] );
245
+
246
+ // Email
247
+ $email = sanitize_email( $_POST['email'] );
248
+
249
+ // URL
250
+ $url = esc_url_raw( $_POST['url'] );
251
+
252
+ // Integer
253
+ $number = absint( $_POST['number'] );
254
+
255
+ // Array
256
+ $array = array_map( 'sanitize_text_field', $_POST['array'] );
257
+
258
+ // HTML (allowed tags)
259
+ $html = wp_kses_post( $_POST['content'] );
260
+ ```
261
+
262
+ ### Output Escaping
263
+
264
+ **Always Escape Output**:
265
+
266
+ ```php
267
+ // HTML
268
+ echo esc_html( $text );
269
+
270
+ // Attributes
271
+ echo '<div class="' . esc_attr( $class ) . '">';
272
+
273
+ // URL
274
+ echo '<a href="' . esc_url( $url ) . '">';
275
+
276
+ // JavaScript
277
+ echo '<script>var data = ' . wp_json_encode( $data ) . ';</script>';
278
+
279
+ // Translation with escaping
280
+ echo esc_html__( 'Text', 'text-domain' );
281
+ ```
282
+
283
+ ### Nonce Verification
284
+
285
+ **Always Use Nonces for Forms**:
286
+
287
+ ```php
288
+ // Create nonce
289
+ wp_nonce_field( 'action_name', 'nonce_name' );
290
+
291
+ // Verify nonce
292
+ if ( ! isset( $_POST['nonce_name'] ) || ! wp_verify_nonce( $_POST['nonce_name'], 'action_name' ) ) {
293
+ wp_die( __( 'Security check failed', 'text-domain' ) );
294
+ }
295
+ ```
296
+
297
+ **Nonces for AJAX**:
298
+
299
+ ```php
300
+ // Create nonce for AJAX
301
+ wp_localize_script( 'script-handle', 'ajax_object', array(
302
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
303
+ 'nonce' => wp_create_nonce( 'ajax_nonce' ),
304
+ ) );
305
+
306
+ // Verify in AJAX handler
307
+ check_ajax_referer( 'ajax_nonce', 'nonce' );
308
+ ```
309
+
310
+ ### Capability Checks
311
+
312
+ **Always Check User Capabilities**:
313
+
314
+ ```php
315
+ // Admin actions
316
+ if ( ! current_user_can( 'manage_options' ) ) {
317
+ wp_die( __( 'Insufficient permissions', 'text-domain' ) );
318
+ }
319
+
320
+ // Post editing
321
+ if ( ! current_user_can( 'edit_post', $post_id ) ) {
322
+ return;
323
+ }
324
+
325
+ // Custom capability
326
+ if ( ! current_user_can( 'plugin_name_custom_capability' ) ) {
327
+ return;
328
+ }
329
+ ```
330
+
331
+ ### Database Security
332
+
333
+ **Use Prepared Statements**:
334
+
335
+ ```php
336
+ global $wpdb;
337
+
338
+ // Prepared statement
339
+ $results = $wpdb->get_results( $wpdb->prepare(
340
+ "SELECT * FROM {$wpdb->prefix}table WHERE column = %s AND id = %d",
341
+ $string_value,
342
+ $int_value
343
+ ) );
344
+
345
+ // Never use direct queries
346
+ // BAD: $wpdb->query( "SELECT * FROM table WHERE id = " . $_GET['id'] );
347
+ ```
348
+
349
+ ### File Security
350
+
351
+ **Prevent Direct Access**:
352
+
353
+ ```php
354
+ // Add to all PHP files
355
+ if ( ! defined( 'ABSPATH' ) ) {
356
+ exit; // Exit if accessed directly
357
+ }
358
+ ```
359
+
360
+ **Validate File Uploads**:
361
+
362
+ ```php
363
+ function plugin_name_validate_upload( $file ) {
364
+ // Check file type
365
+ $allowed_types = array( 'image/jpeg', 'image/png', 'image/gif' );
366
+ if ( ! in_array( $file['type'], $allowed_types, true ) ) {
367
+ return new WP_Error( 'invalid_type', __( 'Invalid file type', 'text-domain' ) );
368
+ }
369
+
370
+ // Check file size (5MB max)
371
+ if ( $file['size'] > 5 * 1024 * 1024 ) {
372
+ return new WP_Error( 'file_too_large', __( 'File too large', 'text-domain' ) );
373
+ }
374
+
375
+ return $file;
376
+ }
377
+ ```
378
+
379
+ ### Security Checklist
380
+
381
+ - [ ] All user input is sanitized
382
+ - [ ] All output is escaped
383
+ - [ ] Nonces are used for all forms
384
+ - [ ] Capability checks are in place
385
+ - [ ] Database queries use prepared statements
386
+ - [ ] Direct file access is prevented
387
+ - [ ] File uploads are validated
388
+ - [ ] No eval() or exec() usage
389
+ - [ ] No unserialize() on user input
390
+ - [ ] No file_get_contents() on user input
391
+ - [ ] HTTPS is used for external requests
392
+ - [ ] API keys are stored securely (not in code)
393
+
394
+ ## Performance Checklist
395
+
396
+ ### Database Optimization
397
+
398
+ **Optimize Queries**:
399
+
400
+ ```php
401
+ // Use WP_Query efficiently
402
+ $args = array(
403
+ 'post_type' => 'post',
404
+ 'posts_per_page' => 10,
405
+ 'no_found_rows' => true, // Skip pagination count
406
+ 'update_post_meta_cache' => false, // Skip meta cache if not needed
407
+ 'update_post_term_cache' => false, // Skip term cache if not needed
408
+ );
409
+ $query = new WP_Query( $args );
410
+
411
+ // Avoid N+1 queries
412
+ // BAD: Loop through posts and get meta for each
413
+ // GOOD: Use update_post_meta_cache or get all meta at once
414
+ ```
415
+
416
+ **Use Transients for Caching**:
417
+
418
+ ```php
419
+ function plugin_name_get_expensive_data() {
420
+ $cache_key = 'plugin_name_expensive_data';
421
+ $data = get_transient( $cache_key );
422
+
423
+ if ( false === $data ) {
424
+ // Expensive operation
425
+ $data = perform_expensive_operation();
426
+
427
+ // Cache for 1 hour
428
+ set_transient( $cache_key, $data, HOUR_IN_SECONDS );
429
+ }
430
+
431
+ return $data;
432
+ }
433
+ ```
434
+
435
+ **Use Object Caching**:
436
+
437
+ ```php
438
+ function plugin_name_get_data( $id ) {
439
+ $cache_key = 'plugin_name_data_' . $id;
440
+ $data = wp_cache_get( $cache_key, 'plugin_name' );
441
+
442
+ if ( false === $data ) {
443
+ $data = get_data_from_database( $id );
444
+ wp_cache_set( $cache_key, $data, 'plugin_name', 3600 );
445
+ }
446
+
447
+ return $data;
448
+ }
449
+ ```
450
+
451
+ ### Asset Optimization
452
+
453
+ **Conditional Loading**:
454
+
455
+ ```php
456
+ function plugin_name_enqueue_scripts() {
457
+ // Only load on specific pages
458
+ if ( is_singular( 'post' ) ) {
459
+ wp_enqueue_script( 'plugin-name-script', plugins_url( 'js/script.js', __FILE__ ), array( 'jquery' ), '1.0.0', true );
460
+ }
461
+
462
+ // Only load in admin
463
+ if ( is_admin() ) {
464
+ wp_enqueue_style( 'plugin-name-admin', plugins_url( 'css/admin.css', __FILE__ ), array(), '1.0.0' );
465
+ }
466
+ }
467
+ add_action( 'wp_enqueue_scripts', 'plugin_name_enqueue_scripts' );
468
+ ```
469
+
470
+ **Minify and Combine Assets**:
471
+
472
+ ```php
473
+ // Use .min versions in production
474
+ $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
475
+ wp_enqueue_script( 'plugin-name-script', plugins_url( "js/script{$suffix}.js", __FILE__ ), array( 'jquery' ), '1.0.0', true );
476
+ ```
477
+
478
+ **Lazy Load Images**:
479
+
480
+ ```php
481
+ function plugin_name_add_lazy_loading( $content ) {
482
+ if ( is_singular() ) {
483
+ $content = str_replace( '<img ', '<img loading="lazy" ', $content );
484
+ }
485
+ return $content;
486
+ }
487
+ add_filter( 'the_content', 'plugin_name_add_lazy_loading' );
488
+ ```
489
+
490
+ ### Cron Job Optimization
491
+
492
+ **Use WP-Cron Efficiently**:
493
+
494
+ ```php
495
+ // Schedule event
496
+ if ( ! wp_next_scheduled( 'plugin_name_daily_task' ) ) {
497
+ wp_schedule_event( time(), 'daily', 'plugin_name_daily_task' );
498
+ }
499
+
500
+ // Hook callback
501
+ add_action( 'plugin_name_daily_task', 'plugin_name_do_daily_task' );
502
+
503
+ function plugin_name_do_daily_task() {
504
+ // Batch process large datasets
505
+ $offset = get_option( 'plugin_name_batch_offset', 0 );
506
+ $batch_size = 100;
507
+
508
+ // Process batch
509
+ $items = get_items( $offset, $batch_size );
510
+ foreach ( $items as $item ) {
511
+ process_item( $item );
512
+ }
513
+
514
+ // Update offset
515
+ update_option( 'plugin_name_batch_offset', $offset + $batch_size );
516
+ }
517
+ ```
518
+
519
+ ### Performance Checklist
520
+
521
+ - [ ] Database queries are optimized
522
+ - [ ] Transients are used for expensive operations
523
+ - [ ] Object caching is implemented
524
+ - [ ] Assets are loaded conditionally
525
+ - [ ] Assets are minified
526
+ - [ ] Images use lazy loading
527
+ - [ ] Cron jobs are optimized
528
+ - [ ] No queries in loops
529
+ - [ ] Pagination is implemented for large datasets
530
+ - [ ] External API calls are cached
531
+
532
+ ## Accessibility Considerations
533
+
534
+ ### Semantic HTML
535
+
536
+ **Use Proper HTML Elements**:
537
+
538
+ ```php
539
+ // Good
540
+ echo '<button type="button">' . esc_html__( 'Click Me', 'text-domain' ) . '</button>';
541
+
542
+ // Bad
543
+ echo '<div onclick="doSomething()">' . esc_html__( 'Click Me', 'text-domain' ) . '</div>';
544
+ ```
545
+
546
+ ### ARIA Labels
547
+
548
+ **Add ARIA Labels for Screen Readers**:
549
+
550
+ ```php
551
+ echo '<button type="button" aria-label="' . esc_attr__( 'Close dialog', 'text-domain' ) . '">';
552
+ echo '<span aria-hidden="true">&times;</span>';
553
+ echo '</button>';
554
+ ```
555
+
556
+ ### Keyboard Navigation
557
+
558
+ **Ensure Keyboard Accessibility**:
559
+
560
+ ```php
561
+ // Add tabindex for custom interactive elements
562
+ echo '<div tabindex="0" role="button" onkeypress="handleKeyPress(event)">';
563
+ echo esc_html__( 'Custom Button', 'text-domain' );
564
+ echo '</div>';
565
+ ```
566
+
567
+ ### Form Labels
568
+
569
+ **Always Label Form Fields**:
570
+
571
+ ```php
572
+ echo '<label for="plugin-name-field">' . esc_html__( 'Field Label', 'text-domain' ) . '</label>';
573
+ echo '<input type="text" id="plugin-name-field" name="field_name" />';
574
+ ```
575
+
576
+ ### Color Contrast
577
+
578
+ **Ensure Sufficient Color Contrast**:
579
+
580
+ ```css
581
+ /* WCAG AA requires 4.5:1 contrast ratio for normal text */
582
+ .plugin-name-text {
583
+ color: #333333; /* Dark gray on white background */
584
+ background-color: #ffffff;
585
+ }
586
+
587
+ /* WCAG AAA requires 7:1 contrast ratio */
588
+ .plugin-name-important {
589
+ color: #000000; /* Black on white background */
590
+ background-color: #ffffff;
591
+ }
592
+ ```
593
+
594
+ ### Accessibility Checklist
595
+
596
+ - [ ] Semantic HTML is used
597
+ - [ ] ARIA labels are provided
598
+ - [ ] Keyboard navigation works
599
+ - [ ] Form fields have labels
600
+ - [ ] Color contrast meets WCAG AA standards
601
+ - [ ] Images have alt text
602
+ - [ ] Focus indicators are visible
603
+ - [ ] Skip links are provided
604
+ - [ ] Headings are hierarchical
605
+ - [ ] Error messages are descriptive
606
+
607
+ ## Backward Compatibility
608
+
609
+ ### WordPress Version Compatibility
610
+
611
+ **Check WordPress Version**:
612
+
613
+ ```php
614
+ function plugin_name_check_version() {
615
+ global $wp_version;
616
+
617
+ if ( version_compare( $wp_version, '6.0', '<' ) ) {
618
+ add_action( 'admin_notices', 'plugin_name_version_notice' );
619
+ return false;
620
+ }
621
+
622
+ return true;
623
+ }
624
+
625
+ function plugin_name_version_notice() {
626
+ echo '<div class="notice notice-error"><p>';
627
+ echo esc_html__( 'Plugin Name requires WordPress 6.0 or higher.', 'text-domain' );
628
+ echo '</p></div>';
629
+ }
630
+ ```
631
+
632
+ ### PHP Version Compatibility
633
+
634
+ **Check PHP Version**:
635
+
636
+ ```php
637
+ if ( version_compare( PHP_VERSION, '7.4', '<' ) ) {
638
+ add_action( 'admin_notices', function() {
639
+ echo '<div class="notice notice-error"><p>';
640
+ echo esc_html__( 'Plugin Name requires PHP 7.4 or higher.', 'text-domain' );
641
+ echo '</p></div>';
642
+ } );
643
+ return;
644
+ }
645
+ ```
646
+
647
+ ### Deprecation Handling
648
+
649
+ **Handle Deprecated Functions**:
650
+
651
+ ```php
652
+ function plugin_name_old_function() {
653
+ _deprecated_function( __FUNCTION__, '2.0.0', 'plugin_name_new_function' );
654
+ return plugin_name_new_function();
655
+ }
656
+
657
+ function plugin_name_new_function() {
658
+ // New implementation
659
+ }
660
+ ```
661
+
662
+ ### Database Schema Updates
663
+
664
+ **Version Database Schema**:
665
+
666
+ ```php
667
+ function plugin_name_update_database() {
668
+ $current_version = get_option( 'plugin_name_db_version', '1.0' );
669
+
670
+ if ( version_compare( $current_version, '2.0', '<' ) ) {
671
+ plugin_name_upgrade_to_2_0();
672
+ update_option( 'plugin_name_db_version', '2.0' );
673
+ }
674
+ }
675
+
676
+ function plugin_name_upgrade_to_2_0() {
677
+ global $wpdb;
678
+
679
+ // Add new column
680
+ $wpdb->query( "ALTER TABLE {$wpdb->prefix}plugin_name_table ADD COLUMN new_column VARCHAR(255)" );
681
+ }
682
+ ```
683
+
684
+ ### Backward Compatibility Checklist
685
+
686
+ - [ ] Minimum WordPress version is specified
687
+ - [ ] Minimum PHP version is specified
688
+ - [ ] Version checks are in place
689
+ - [ ] Deprecated functions use _deprecated_function()
690
+ - [ ] Database schema updates are versioned
691
+ - [ ] Settings migration is handled
692
+ - [ ] Old hooks are maintained (with deprecation notices)
693
+ - [ ] Breaking changes are documented
694
+ - [ ] Upgrade path is tested
695
+
696
+ ## Internationalization (i18n)
697
+
698
+ ### Text Domain
699
+
700
+ **Use Consistent Text Domain**:
701
+
702
+ ```php
703
+ // In plugin header
704
+ /*
705
+ * Text Domain: plugin-name
706
+ * Domain Path: /languages
707
+ */
708
+
709
+ // In code
710
+ __( 'Text', 'plugin-name' );
711
+ _e( 'Text', 'plugin-name' );
712
+ esc_html__( 'Text', 'plugin-name' );
713
+ esc_html_e( 'Text', 'plugin-name' );
714
+ ```
715
+
716
+ ### Load Text Domain
717
+
718
+ **Load Translations**:
719
+
720
+ ```php
721
+ function plugin_name_load_textdomain() {
722
+ load_plugin_textdomain( 'plugin-name', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
723
+ }
724
+ add_action( 'plugins_loaded', 'plugin_name_load_textdomain' );
725
+ ```
726
+
727
+ ### Translatable Strings
728
+
729
+ **Make All User-Facing Strings Translatable**:
730
+
731
+ ```php
732
+ // Simple string
733
+ echo esc_html__( 'Hello World', 'plugin-name' );
734
+
735
+ // String with context
736
+ echo esc_html_x( 'Post', 'noun', 'plugin-name' );
737
+
738
+ // Plural
739
+ echo esc_html( sprintf(
740
+ _n( '%d item', '%d items', $count, 'plugin-name' ),
741
+ $count
742
+ ) );
743
+ ```
744
+
745
+ ## Documentation Standards
746
+
747
+ ### PHPDoc Comments
748
+
749
+ **Document All Functions and Classes**:
750
+
751
+ ```php
752
+ /**
753
+ * Process user data
754
+ *
755
+ * @since 1.0.0
756
+ * @param array $data The user data to process.
757
+ * @param bool $validate Whether to validate the data.
758
+ * @return array|WP_Error Processed data or error.
759
+ */
760
+ function plugin_name_process_data( $data, $validate = true ) {
761
+ // Implementation
762
+ }
763
+ ```
764
+
765
+ ### Inline Comments
766
+
767
+ **Add Explanatory Comments**:
768
+
769
+ ```php
770
+ // Check if user has permission
771
+ if ( ! current_user_can( 'manage_options' ) ) {
772
+ return;
773
+ }
774
+
775
+ // Process data in batches to avoid memory issues
776
+ $batch_size = 100;
777
+ for ( $i = 0; $i < count( $items ); $i += $batch_size ) {
778
+ $batch = array_slice( $items, $i, $batch_size );
779
+ process_batch( $batch );
780
+ }
781
+ ```
782
+
783
+ ### README Documentation
784
+
785
+ **Maintain Comprehensive README**:
786
+
787
+ ```markdown
788
+ # Plugin Name
789
+
790
+ ## Description
791
+ Brief description of what the plugin does.
792
+
793
+ ## Installation
794
+ 1. Upload plugin files
795
+ 2. Activate plugin
796
+ 3. Configure settings
797
+
798
+ ## Usage
799
+ How to use the plugin.
800
+
801
+ ## Hooks
802
+ List of available hooks and filters.
803
+
804
+ ## Changelog
805
+ Version history with changes.
806
+ ```
807
+
808
+ ## Testing Best Practices
809
+
810
+ ### Write Tests First (TDD)
811
+
812
+ ```php
813
+ // Write test first
814
+ public function test_sanitizes_email() {
815
+ $input = 'test@EXAMPLE.com';
816
+ $expected = 'test@example.com';
817
+ $result = plugin_name_sanitize_email( $input );
818
+ $this->assertEquals( $expected, $result );
819
+ }
820
+
821
+ // Then implement function
822
+ function plugin_name_sanitize_email( $email ) {
823
+ return sanitize_email( strtolower( $email ) );
824
+ }
825
+ ```
826
+
827
+ ### Test Coverage
828
+
829
+ **Aim for > 80% Code Coverage**:
830
+
831
+ ```bash
832
+ vendor/bin/phpunit --coverage-html coverage/
833
+ ```
834
+
835
+ ### Test Different Scenarios
836
+
837
+ ```php
838
+ public function test_handles_empty_input() {
839
+ $result = plugin_name_process( '' );
840
+ $this->assertWPError( $result );
841
+ }
842
+
843
+ public function test_handles_invalid_input() {
844
+ $result = plugin_name_process( 'invalid' );
845
+ $this->assertWPError( $result );
846
+ }
847
+
848
+ public function test_handles_valid_input() {
849
+ $result = plugin_name_process( 'valid' );
850
+ $this->assertNotWPError( $result );
851
+ }
852
+ ```
853
+
854
+ ## Version Control Best Practices
855
+
856
+ ### Git Workflow
857
+
858
+ **Use Feature Branches**:
859
+
860
+ ```bash
861
+ git checkout -b feature/new-feature
862
+ # Make changes
863
+ git commit -m "feat: Add new feature"
864
+ git push origin feature/new-feature
865
+ ```
866
+
867
+ ### Commit Messages
868
+
869
+ **Use Conventional Commits**:
870
+
871
+ ```
872
+ feat: Add new feature
873
+ fix: Fix bug in data processing
874
+ docs: Update README
875
+ style: Format code
876
+ refactor: Refactor data processing
877
+ test: Add tests for new feature
878
+ chore: Update dependencies
879
+ ```
880
+
881
+ ### .gitignore
882
+
883
+ **Ignore Unnecessary Files**:
884
+
885
+ ```
886
+ # .gitignore
887
+ node_modules/
888
+ vendor/
889
+ .DS_Store
890
+ *.log
891
+ coverage/
892
+ .phpunit.result.cache
893
+ ```
894
+
895
+ ## Release Checklist
896
+
897
+ ### Pre-Release
898
+
899
+ - [ ] All tests pass
900
+ - [ ] Code coverage > 80%
901
+ - [ ] Security audit complete
902
+ - [ ] WPCS compliance verified
903
+ - [ ] Documentation updated
904
+ - [ ] Changelog updated
905
+ - [ ] Version number updated
906
+ - [ ] Translation files generated
907
+
908
+ ### Release
909
+
910
+ - [ ] Create git tag
911
+ - [ ] Create release notes
912
+ - [ ] Update WordPress.org SVN
913
+ - [ ] Test in clean WordPress install
914
+ - [ ] Monitor for issues
915
+
916
+ ### Post-Release
917
+
918
+ - [ ] Monitor support forums
919
+ - [ ] Respond to user feedback
920
+ - [ ] Track bug reports
921
+ - [ ] Plan next release
922
+
923
+ ## Resources
924
+
925
+ - [WordPress Plugin Handbook](https://developer.wordpress.org/plugins/)
926
+ - [WordPress Coding Standards](https://developer.wordpress.org/coding-standards/)
927
+ - [WordPress Security Best Practices](https://developer.wordpress.org/plugins/security/)
928
+ - [WCAG Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
929
+ - [Semantic Versioning](https://semver.org/)
930
+
931
+ ## Related Workflows
932
+
933
+ - `development-workflow.md` - Feature development cycle
934
+ - `testing-workflow.md` - Testing setup and execution
935
+ - `submission-workflow.md` - WordPress.org submission
936
+
937
+ ## Related Domain Rules
938
+
939
+ - `domain-rules/wordpress-plugin/security-best-practices.md`
940
+ - `domain-rules/wordpress-plugin/performance-optimization.md`
941
+ - `domain-rules/wordpress-plugin/internationalization.md`
942
+