ima-claude 2.9.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 (182) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +463 -0
  3. package/dist/cli.js +1064 -0
  4. package/package.json +49 -0
  5. package/platforms/claude/adapter.ts +115 -0
  6. package/platforms/junie/adapter.ts +254 -0
  7. package/platforms/junie/agents-template.md +113 -0
  8. package/platforms/junie/hook-translations.md +84 -0
  9. package/platforms/shared/detector.ts +27 -0
  10. package/platforms/shared/installer.ts +202 -0
  11. package/platforms/shared/types.ts +78 -0
  12. package/plugins/ima-claude/.claude-plugin/plugin.json +25 -0
  13. package/plugins/ima-claude/agents/explorer.md +30 -0
  14. package/plugins/ima-claude/agents/implementer.md +30 -0
  15. package/plugins/ima-claude/agents/memory.md +42 -0
  16. package/plugins/ima-claude/agents/reviewer.md +53 -0
  17. package/plugins/ima-claude/agents/tester.md +33 -0
  18. package/plugins/ima-claude/agents/wp-developer.md +46 -0
  19. package/plugins/ima-claude/hooks/README.md +145 -0
  20. package/plugins/ima-claude/hooks/atlassian_prereqs.py +112 -0
  21. package/plugins/ima-claude/hooks/block_sed_edits.py +59 -0
  22. package/plugins/ima-claude/hooks/bootstrap.sh +90 -0
  23. package/plugins/ima-claude/hooks/bootstrap_utility_check.py +94 -0
  24. package/plugins/ima-claude/hooks/composer_autoload_check.py +70 -0
  25. package/plugins/ima-claude/hooks/docs_organization.py +104 -0
  26. package/plugins/ima-claude/hooks/enforce_rg_over_grep.py +56 -0
  27. package/plugins/ima-claude/hooks/fp_utility_check.py +90 -0
  28. package/plugins/ima-claude/hooks/hook_logger.py +69 -0
  29. package/plugins/ima-claude/hooks/hooks.json +239 -0
  30. package/plugins/ima-claude/hooks/jira_issue_fetch.py +79 -0
  31. package/plugins/ima-claude/hooks/jquery_in_wordpress.py +92 -0
  32. package/plugins/ima-claude/hooks/memory_bootstrap.py +79 -0
  33. package/plugins/ima-claude/hooks/memory_store_reminder.py +75 -0
  34. package/plugins/ima-claude/hooks/prompt_coach.py +125 -0
  35. package/plugins/ima-claude/hooks/prompt_coach_digest.md +48 -0
  36. package/plugins/ima-claude/hooks/prompt_coach_system.md +30 -0
  37. package/plugins/ima-claude/hooks/sequential_thinking_check.py +81 -0
  38. package/plugins/ima-claude/hooks/serena_over_grep.py +96 -0
  39. package/plugins/ima-claude/hooks/serena_over_read.py +66 -0
  40. package/plugins/ima-claude/hooks/serena_project_check.py +133 -0
  41. package/plugins/ima-claude/hooks/sql_injection_check.py +73 -0
  42. package/plugins/ima-claude/hooks/task_master_after_plan.py +31 -0
  43. package/plugins/ima-claude/hooks/task_master_before_impl.py +93 -0
  44. package/plugins/ima-claude/hooks/tavily_extract_advanced.py +48 -0
  45. package/plugins/ima-claude/hooks/vestige_before_external.py +86 -0
  46. package/plugins/ima-claude/hooks/webfetch_to_tavily.py +42 -0
  47. package/plugins/ima-claude/hooks/websearch_to_tavily.py +41 -0
  48. package/plugins/ima-claude/hooks/wp_security_check.py +150 -0
  49. package/plugins/ima-claude/personalities/README.md +45 -0
  50. package/plugins/ima-claude/personalities/enable-40k.md +69 -0
  51. package/plugins/ima-claude/personalities/enable-templars.md +69 -0
  52. package/plugins/ima-claude/skills/.research-summary.md +340 -0
  53. package/plugins/ima-claude/skills/architect/SKILL.md +304 -0
  54. package/plugins/ima-claude/skills/compound-bridge/SKILL.md +200 -0
  55. package/plugins/ima-claude/skills/discourse/SKILL.md +440 -0
  56. package/plugins/ima-claude/skills/discourse-admin/SKILL.md +192 -0
  57. package/plugins/ima-claude/skills/discourse-admin/references/api-endpoints.md +441 -0
  58. package/plugins/ima-claude/skills/discourse-admin/references/gotchas.md +107 -0
  59. package/plugins/ima-claude/skills/discourse-admin/references/staging-defaults.md +98 -0
  60. package/plugins/ima-claude/skills/discourse-admin/scripts/discourse-admin.py +319 -0
  61. package/plugins/ima-claude/skills/docs-organize/SKILL.md +254 -0
  62. package/plugins/ima-claude/skills/docs-organize/templates/active-README.md +50 -0
  63. package/plugins/ima-claude/skills/docs-organize/templates/archive-README.md +57 -0
  64. package/plugins/ima-claude/skills/docs-organize/templates/docs-README.md +43 -0
  65. package/plugins/ima-claude/skills/docs-organize/templates/phase-archive-README.md +83 -0
  66. package/plugins/ima-claude/skills/docs-organize/templates/section-README.md +48 -0
  67. package/plugins/ima-claude/skills/docs-organize/templates/transient-README.md +79 -0
  68. package/plugins/ima-claude/skills/docs-organize/templates/transient-gitignore +9 -0
  69. package/plugins/ima-claude/skills/ember-discourse/SKILL.md +496 -0
  70. package/plugins/ima-claude/skills/functional-programmer/SKILL.md +258 -0
  71. package/plugins/ima-claude/skills/ima-bootstrap/SKILL.md +278 -0
  72. package/plugins/ima-claude/skills/ima-bootstrap/references/bootstrap-patterns.md +356 -0
  73. package/plugins/ima-claude/skills/ima-bootstrap/references/ima-brand.md +273 -0
  74. package/plugins/ima-claude/skills/ima-bootstrap/references/theme-integration.md +212 -0
  75. package/plugins/ima-claude/skills/ima-brand/SKILL.md +108 -0
  76. package/plugins/ima-claude/skills/ima-brand/references/brand-identity.md +140 -0
  77. package/plugins/ima-claude/skills/ima-brand/references/digital-standards.md +180 -0
  78. package/plugins/ima-claude/skills/ima-brand/references/visual-system.md +173 -0
  79. package/plugins/ima-claude/skills/ima-forms-expert/SKILL.md +175 -0
  80. package/plugins/ima-claude/skills/ima-forms-expert/references/container-components.md +154 -0
  81. package/plugins/ima-claude/skills/ima-forms-expert/references/examples.md +328 -0
  82. package/plugins/ima-claude/skills/ima-forms-expert/references/field-components.md +298 -0
  83. package/plugins/ima-claude/skills/ima-forms-expert/references/form-factory.md +193 -0
  84. package/plugins/ima-claude/skills/ima-forms-expert/references/quick-reference.md +153 -0
  85. package/plugins/ima-claude/skills/ima-forms-expert/references/validation-engine.md +336 -0
  86. package/plugins/ima-claude/skills/jira-checkpoint/SKILL.md +178 -0
  87. package/plugins/ima-claude/skills/jquery/SKILL.md +413 -0
  88. package/plugins/ima-claude/skills/js-fp/SKILL.md +463 -0
  89. package/plugins/ima-claude/skills/js-fp/core-principles.md +487 -0
  90. package/plugins/ima-claude/skills/js-fp/examples/pure-functions.js +260 -0
  91. package/plugins/ima-claude/skills/js-fp/examples/tests/pure-functions.test.js +262 -0
  92. package/plugins/ima-claude/skills/js-fp/references/anti-patterns.md +120 -0
  93. package/plugins/ima-claude/skills/js-fp/references/performance-patterns.md +116 -0
  94. package/plugins/ima-claude/skills/js-fp/references/testing-patterns.md +134 -0
  95. package/plugins/ima-claude/skills/js-fp-api/SKILL.md +280 -0
  96. package/plugins/ima-claude/skills/js-fp-api/examples/crud-endpoint.js +258 -0
  97. package/plugins/ima-claude/skills/js-fp-api/references/middleware-patterns.md +134 -0
  98. package/plugins/ima-claude/skills/js-fp-api/references/security-sql.md +110 -0
  99. package/plugins/ima-claude/skills/js-fp-api/references/validation-patterns.md +165 -0
  100. package/plugins/ima-claude/skills/js-fp-react/SKILL.md +447 -0
  101. package/plugins/ima-claude/skills/js-fp-react/examples/ProductCard.tsx +65 -0
  102. package/plugins/ima-claude/skills/js-fp-react/references/hooks-advanced.md +136 -0
  103. package/plugins/ima-claude/skills/js-fp-react/references/performance-patterns.md +175 -0
  104. package/plugins/ima-claude/skills/js-fp-vue/SKILL.md +322 -0
  105. package/plugins/ima-claude/skills/js-fp-vue/references/complete-examples.md +397 -0
  106. package/plugins/ima-claude/skills/js-fp-vue/references/composables-advanced.md +282 -0
  107. package/plugins/ima-claude/skills/js-fp-vue/references/reactivity-patterns.md +348 -0
  108. package/plugins/ima-claude/skills/js-fp-vue/references/testing.md +314 -0
  109. package/plugins/ima-claude/skills/js-fp-wordpress/SKILL.md +301 -0
  110. package/plugins/ima-claude/skills/js-fp-wordpress/references/ajax-patterns.md +192 -0
  111. package/plugins/ima-claude/skills/js-fp-wordpress/references/event-patterns.md +136 -0
  112. package/plugins/ima-claude/skills/js-fp-wordpress/references/wp-integration.md +248 -0
  113. package/plugins/ima-claude/skills/livecanvas/SKILL.md +209 -0
  114. package/plugins/ima-claude/skills/livecanvas/references/livecanvas-features.md +311 -0
  115. package/plugins/ima-claude/skills/livecanvas/references/loops-and-logic.md +730 -0
  116. package/plugins/ima-claude/skills/livecanvas/references/picostrap.md +227 -0
  117. package/plugins/ima-claude/skills/mcp-atlassian/SKILL.md +339 -0
  118. package/plugins/ima-claude/skills/mcp-context7/SKILL.md +109 -0
  119. package/plugins/ima-claude/skills/mcp-memory/SKILL.md +182 -0
  120. package/plugins/ima-claude/skills/mcp-qdrant/SKILL.md +233 -0
  121. package/plugins/ima-claude/skills/mcp-sequential/SKILL.md +149 -0
  122. package/plugins/ima-claude/skills/mcp-serena/SKILL.md +174 -0
  123. package/plugins/ima-claude/skills/mcp-tavily/SKILL.md +118 -0
  124. package/plugins/ima-claude/skills/mcp-vestige/SKILL.md +259 -0
  125. package/plugins/ima-claude/skills/php-authnet/SKILL.md +275 -0
  126. package/plugins/ima-claude/skills/php-authnet/references/api-reference.md +624 -0
  127. package/plugins/ima-claude/skills/php-authnet/references/sandbox-testing.md +424 -0
  128. package/plugins/ima-claude/skills/php-fp/SKILL.md +333 -0
  129. package/plugins/ima-claude/skills/php-fp/examples/pure-functions.php +403 -0
  130. package/plugins/ima-claude/skills/php-fp/examples/tests/PureFunctionsTest.php +515 -0
  131. package/plugins/ima-claude/skills/php-fp/references/core-principles.md +277 -0
  132. package/plugins/ima-claude/skills/php-fp/references/testing-patterns.md +374 -0
  133. package/plugins/ima-claude/skills/php-fp-wordpress/SKILL.md +216 -0
  134. package/plugins/ima-claude/skills/php-fp-wordpress/references/fp-patterns.md +275 -0
  135. package/plugins/ima-claude/skills/php-fp-wordpress/references/plugin-architecture.md +295 -0
  136. package/plugins/ima-claude/skills/php-fp-wordpress/references/security-examples.md +203 -0
  137. package/plugins/ima-claude/skills/php-fp-wordpress/references/testing-strategy.md +259 -0
  138. package/plugins/ima-claude/skills/phpunit-wp/SKILL.md +716 -0
  139. package/plugins/ima-claude/skills/playwright/SKILL.md +434 -0
  140. package/plugins/ima-claude/skills/playwright/references/accessibility-testing.md +153 -0
  141. package/plugins/ima-claude/skills/playwright/references/ci-cd.md +268 -0
  142. package/plugins/ima-claude/skills/playwright/references/network-mocking.md +270 -0
  143. package/plugins/ima-claude/skills/playwright/references/visual-regression.md +215 -0
  144. package/plugins/ima-claude/skills/py-fp/SKILL.md +663 -0
  145. package/plugins/ima-claude/skills/py-fp/examples/pure-functions.py +185 -0
  146. package/plugins/ima-claude/skills/py-fp/examples/tests/test_pure_functions.py +244 -0
  147. package/plugins/ima-claude/skills/py-fp/references/core-principles.md +381 -0
  148. package/plugins/ima-claude/skills/py-fp/references/testing-patterns.md +283 -0
  149. package/plugins/ima-claude/skills/quasar-fp/SKILL.md +327 -0
  150. package/plugins/ima-claude/skills/quasar-fp/metadata.json +85 -0
  151. package/plugins/ima-claude/skills/quasar-fp/references/component-patterns.md +257 -0
  152. package/plugins/ima-claude/skills/quasar-fp/references/theme-integration.md +233 -0
  153. package/plugins/ima-claude/skills/quasar-fp/references/utility-classes.md +237 -0
  154. package/plugins/ima-claude/skills/quickstart/SKILL.md +129 -0
  155. package/plugins/ima-claude/skills/rails/SKILL.md +359 -0
  156. package/plugins/ima-claude/skills/resume-session/SKILL.md +68 -0
  157. package/plugins/ima-claude/skills/rg/SKILL.md +205 -0
  158. package/plugins/ima-claude/skills/ruby-fp/SKILL.md +336 -0
  159. package/plugins/ima-claude/skills/save-session/SKILL.md +81 -0
  160. package/plugins/ima-claude/skills/scorecard/SKILL.md +96 -0
  161. package/plugins/ima-claude/skills/skill-analyzer/SKILL.md +127 -0
  162. package/plugins/ima-claude/skills/skill-analyzer/references/advanced-checklist.md +44 -0
  163. package/plugins/ima-claude/skills/skill-analyzer/references/core-checklist.md +60 -0
  164. package/plugins/ima-claude/skills/skill-analyzer/scripts/analyze_skill.py +418 -0
  165. package/plugins/ima-claude/skills/skill-creator/LICENSE.txt +202 -0
  166. package/plugins/ima-claude/skills/skill-creator/SKILL.md +343 -0
  167. package/plugins/ima-claude/skills/skill-creator/references/output-patterns.md +82 -0
  168. package/plugins/ima-claude/skills/skill-creator/references/workflows.md +28 -0
  169. package/plugins/ima-claude/skills/skill-creator/scripts/init_skill.py +303 -0
  170. package/plugins/ima-claude/skills/skill-creator/scripts/package_skill.py +110 -0
  171. package/plugins/ima-claude/skills/skill-creator/scripts/quick_validate.py +103 -0
  172. package/plugins/ima-claude/skills/task-master/SKILL.md +51 -0
  173. package/plugins/ima-claude/skills/task-planner/SKILL.md +228 -0
  174. package/plugins/ima-claude/skills/task-runner/SKILL.md +192 -0
  175. package/plugins/ima-claude/skills/unit-testing/SKILL.md +198 -0
  176. package/plugins/ima-claude/skills/unit-testing/references/mock-patterns.md +181 -0
  177. package/plugins/ima-claude/skills/unit-testing/references/tdd-workflow.md +177 -0
  178. package/plugins/ima-claude/skills/unit-testing/references/test-strategy.md +126 -0
  179. package/plugins/ima-claude/skills/wp-local/SKILL.md +246 -0
  180. package/plugins/ima-claude/skills/wp-local/references/configuration.md +198 -0
  181. package/plugins/ima-claude/skills/wp-local/references/wp-cli-reference.md +406 -0
  182. package/plugins/ima-claude/skills/wp-local/scripts/wp-local.sh +61 -0
@@ -0,0 +1,216 @@
1
+ ---
2
+ name: "php-fp-wordpress"
3
+ description: "Security-first WordPress development with PHP FP principles - pure business logic + WordPress integration"
4
+ ---
5
+
6
+ # PHP FP - WordPress
7
+
8
+ Security-first WordPress development combining PHP functional programming principles with mandatory WordPress security practices.
9
+
10
+ ## When to Use This Skill
11
+
12
+ - Building WordPress plugins or themes
13
+ - Need security-first development practices
14
+ - Implementing pure business logic with WordPress integration
15
+ - Testing WordPress functionality
16
+
17
+ ## Core Philosophy
18
+
19
+ **Security practices prevent vulnerabilities, not architectural patterns.**
20
+
21
+ Hybrid approach:
22
+ 1. **Pure functions** for business logic (testable, no WordPress deps)
23
+ 2. **WordPress wrappers** with mandatory security (capability, nonce, sanitize, escape, prepare)
24
+
25
+ **Foundation**: Reference `../php-fp/SKILL.md` for PHP FP core principles.
26
+
27
+ ## The 5 Non-Negotiable Security Practices
28
+
29
+ **Evidence**: Analysis of 7,966 vulnerabilities (2024) shows these prevent 95%+ of WordPress plugin vulnerabilities.
30
+
31
+ | Practice | Prevents | Rule |
32
+ |----------|----------|------|
33
+ | **Capability Checks** | 53% of XSS | `current_user_can()` before ANY privileged operation |
34
+ | **Nonce Verification** | 15-17% CSRF | `wp_verify_nonce()` on ALL form/AJAX submissions |
35
+ | **Input Sanitization** | Injection | Sanitize ALL user input by type |
36
+ | **Output Escaping** | XSS | Escape ALL output by context |
37
+ | **Prepared Statements** | SQL injection | `$wpdb->prepare()` for ALL queries |
38
+
39
+ ### Quick Reference: Security Functions
40
+
41
+ **Sanitization (Input)**:
42
+ | Function | Use For |
43
+ |----------|---------|
44
+ | `sanitize_text_field()` | Plain text |
45
+ | `sanitize_email()` | Email addresses |
46
+ | `absint()` | Positive integers |
47
+ | `wp_kses_post()` | HTML content |
48
+ | `esc_url_raw()` | URLs (for storage) |
49
+
50
+ **Escaping (Output)**:
51
+ | Function | Context |
52
+ |----------|---------|
53
+ | `esc_html()` | HTML body |
54
+ | `esc_attr()` | HTML attributes |
55
+ | `esc_url()` | URLs in href/src |
56
+ | `wp_json_encode()` | JavaScript data |
57
+
58
+ ### Minimal Security Pattern
59
+
60
+ ```php
61
+ <?php
62
+ add_action('wp_ajax_my_action', function() {
63
+ // 1. Capability check
64
+ if (!current_user_can('edit_posts')) {
65
+ wp_send_json_error('Unauthorized', 403);
66
+ }
67
+
68
+ // 2. Nonce verification
69
+ check_ajax_referer('my_action_nonce', 'nonce');
70
+
71
+ // 3. Sanitize input
72
+ $id = absint($_POST['id']);
73
+ $name = sanitize_text_field($_POST['name']);
74
+
75
+ // 4. Use prepared statement
76
+ global $wpdb;
77
+ $result = $wpdb->get_row($wpdb->prepare(
78
+ "SELECT * FROM {$wpdb->prefix}my_table WHERE id = %d",
79
+ $id
80
+ ));
81
+
82
+ // 5. Escape output
83
+ wp_send_json_success(['name' => esc_html($result->name)]);
84
+ });
85
+ ```
86
+
87
+ ## Pure Logic + WordPress Wrapper Pattern
88
+
89
+ **Separate testable business logic from WordPress integration.**
90
+
91
+ ```php
92
+ <?php
93
+ // PURE: Zero WordPress dependencies, fully testable
94
+ namespace MyPlugin\Pure;
95
+
96
+ function calculate_discount(float $price, string $tier): float {
97
+ $rates = ['bronze' => 0.05, 'silver' => 0.10, 'gold' => 0.15];
98
+ return round($price * (1 - ($rates[$tier] ?? 0)), 2);
99
+ }
100
+
101
+ // WRAPPER: WordPress integration with security
102
+ namespace MyPlugin;
103
+
104
+ add_filter('product_price', function($price) {
105
+ if (!is_user_logged_in()) return $price;
106
+
107
+ $tier = get_user_meta(get_current_user_id(), 'tier', true);
108
+ return Pure\calculate_discount($price, $tier);
109
+ });
110
+ ```
111
+
112
+ ## Inter-Plugin Communication: Hooks Only
113
+
114
+ **Rule**: ALL cross-plugin calls use WordPress hooks. NEVER `function_exists()`.
115
+
116
+ Hooks are safe no-ops — if nobody listens, nothing happens. `function_exists()` is tight coupling disguised as loose coupling.
117
+
118
+ ```php
119
+ <?php
120
+ // BAD — tight coupling, breaks silently on rename
121
+ if (function_exists('ima_discourse_refresh_user_meta')) {
122
+ ima_discourse_refresh_user_meta($user_id);
123
+ }
124
+
125
+ // GOOD — fire-and-forget side effect
126
+ do_action('ima_discourse_refresh_user_meta', $user_id);
127
+
128
+ // GOOD — transform with safe default (function composition via WP)
129
+ $result = apply_filters('ima_membership_cancel_subscription', ['success' => true], $user_id, $sub_id);
130
+ ```
131
+
132
+ **Actions** (`do_action`): Side effects — "something happened, react if you care."
133
+ **Filters** (`apply_filters`): Data transformation — chained function composition with a default return.
134
+
135
+ The handler registers itself:
136
+ ```php
137
+ <?php
138
+ // ima-discourse registers once — or doesn't. Either way, callers don't crash.
139
+ add_action('ima_discourse_refresh_user_meta', 'ima_discourse_refresh_user_meta', 10, 1);
140
+ ```
141
+
142
+ **When `function_exists()` is acceptable**: Internal guard clauses within a single plugin checking if its own functions are loaded, or checking PHP extensions (`function_exists('sodium_crypto_secretbox')`).
143
+
144
+ ## Plugin Complexity Guide
145
+
146
+ | Size | Lines | Pattern |
147
+ |------|-------|---------|
148
+ | Simple | <500 | Namespaced functions |
149
+ | Medium | 500-2000 | Classes + pure functions |
150
+ | Complex | 2000+ | DI Container + Services |
151
+
152
+ **Rule**: Start simple, add complexity only when needed.
153
+
154
+ ## File Organization
155
+
156
+ ```
157
+ my-plugin/
158
+ ├── my-plugin.php # Bootstrap
159
+ ├── includes/
160
+ │ └── functions.php # Pure business logic
161
+ ├── admin/
162
+ │ └── ajax-handlers.php # WordPress integration
163
+ └── tests/
164
+ ├── unit/ # Pure function tests (fast)
165
+ └── integration/ # WordPress tests
166
+ ```
167
+
168
+ ## Security Checklist
169
+
170
+ - [ ] Capability checks on all privileged operations
171
+ - [ ] Nonces on all form/AJAX submissions
172
+ - [ ] Input sanitized by type
173
+ - [ ] Output escaped by context
174
+ - [ ] SQL uses `$wpdb->prepare()`
175
+ - [ ] File uploads use `wp_handle_upload()`
176
+ - [ ] No hardcoded credentials
177
+ - [ ] Cross-plugin calls use hooks, not `function_exists()`
178
+
179
+ ## Quality Gates
180
+
181
+ 1. **Security**: All 5 mandatory practices implemented?
182
+ 2. **Pure logic**: Business logic separated from WordPress?
183
+ 3. **Testability**: Pure functions have unit tests?
184
+ 4. **Complexity**: Architecture matches plugin size?
185
+
186
+ ## When to Load Reference Files
187
+
188
+ ### Security Deep-Dive
189
+ **File**: [`references/security-examples.md`](references/security-examples.md)
190
+ **Load when**: Need detailed security patterns, vulnerable vs. safe comparisons
191
+ **Contains**: Full examples for all 5 practices, security function reference tables
192
+
193
+ ### FP Patterns
194
+ **File**: [`references/fp-patterns.md`](references/fp-patterns.md)
195
+ **Load when**: Implementing pure logic + wrapper pattern, function factories
196
+ **Contains**: Complete membership system example, production email validator example
197
+
198
+ ### Plugin Architecture
199
+ **File**: [`references/plugin-architecture.md`](references/plugin-architecture.md)
200
+ **Load when**: Deciding plugin structure, implementing DI container
201
+ **Contains**: Simple/medium/complex plugin patterns, file organization examples
202
+
203
+ ### Testing Strategy
204
+ **File**: [`references/testing-strategy.md`](references/testing-strategy.md)
205
+ **Load when**: Setting up tests, writing security tests
206
+ **Contains**: Unit/integration test examples, minimal mock bootstrap, security test patterns
207
+
208
+ ## Success Metrics
209
+
210
+ - **Security**: Zero vulnerabilities from missing practices
211
+ - **Testability**: 95%+ coverage for pure functions
212
+ - **Maintainability**: Clear separation of concerns
213
+
214
+ ---
215
+
216
+ **Evidence Base**: Analysis of 7,966 WordPress vulnerabilities (2024), WordPress Core Team standards, Wordfence/Patchstack research.
@@ -0,0 +1,275 @@
1
+ # Pure Logic + WordPress Wrapper Patterns
2
+
3
+ ## Table of Contents
4
+ 1. [Core Pattern](#core-pattern)
5
+ 2. [Complete Example: Membership System](#complete-example-membership-system)
6
+ 3. [Function Factory Pattern](#function-factory-pattern)
7
+ 4. [Production Example: Email Validator](#production-example-email-validator)
8
+
9
+ ---
10
+
11
+ ## Core Pattern
12
+
13
+ **Separate pure business logic from WordPress integration.**
14
+
15
+ ```
16
+ ┌─────────────────────────────────────────┐
17
+ │ PURE BUSINESS LOGIC │
18
+ │ • Zero WordPress dependencies │
19
+ │ • Deterministic, testable │
20
+ │ • Returns data, no side effects │
21
+ └─────────────────────────────────────────┘
22
+
23
+
24
+ ┌─────────────────────────────────────────┐
25
+ │ WORDPRESS WRAPPER │
26
+ │ • Security checks (capability, nonce) │
27
+ │ • Input sanitization │
28
+ │ • Database operations │
29
+ │ • Output escaping │
30
+ └─────────────────────────────────────────┘
31
+ ```
32
+
33
+ ---
34
+
35
+ ## Complete Example: Membership System
36
+
37
+ ### Pure Business Logic (Zero WordPress Dependencies)
38
+
39
+ ```php
40
+ <?php
41
+ namespace MyPlugin\BusinessLogic;
42
+
43
+ /**
44
+ * Calculate membership discount
45
+ * @pure - No side effects, deterministic, easily testable
46
+ */
47
+ function calculate_discount(float $price, string $tier, int $days_member): float {
48
+ $tier_multipliers = [
49
+ 'bronze' => 0.05,
50
+ 'silver' => 0.10,
51
+ 'gold' => 0.15,
52
+ 'platinum' => 0.20
53
+ ];
54
+
55
+ $base_discount = $tier_multipliers[$tier] ?? 0;
56
+ $loyalty_bonus = min($days_member / 365 * 0.02, 0.05); // Max 5% loyalty
57
+ $total_discount = min($base_discount + $loyalty_bonus, 0.25); // Max 25%
58
+
59
+ return round($price * (1 - $total_discount), 2);
60
+ }
61
+
62
+ /**
63
+ * Validate membership tier upgrade
64
+ * @pure - Returns validation result, no database queries
65
+ */
66
+ function validate_tier_upgrade(string $current_tier, string $new_tier): array {
67
+ $tier_hierarchy = ['bronze', 'silver', 'gold', 'platinum'];
68
+ $current_level = array_search($current_tier, $tier_hierarchy);
69
+ $new_level = array_search($new_tier, $tier_hierarchy);
70
+
71
+ if ($current_level === false || $new_level === false) {
72
+ return ['valid' => false, 'error' => 'Invalid tier specified'];
73
+ }
74
+
75
+ if ($new_level <= $current_level) {
76
+ return ['valid' => false, 'error' => 'Cannot downgrade or stay at same tier'];
77
+ }
78
+
79
+ return ['valid' => true, 'upgrade_levels' => $new_level - $current_level];
80
+ }
81
+
82
+ /**
83
+ * Format membership data for display
84
+ * @pure - Data transformation only
85
+ */
86
+ function format_membership_display(array $membership): array {
87
+ return [
88
+ 'tier' => ucfirst($membership['tier']),
89
+ 'expires' => date('F j, Y', strtotime($membership['expires'])),
90
+ 'days_remaining' => max(0, (strtotime($membership['expires']) - time()) / DAY_IN_SECONDS),
91
+ 'status' => strtotime($membership['expires']) > time() ? 'Active' : 'Expired'
92
+ ];
93
+ }
94
+ ```
95
+
96
+ ### WordPress Integration Layer
97
+
98
+ ```php
99
+ <?php
100
+ namespace MyPlugin;
101
+
102
+ use MyPlugin\BusinessLogic;
103
+
104
+ /**
105
+ * WordPress filter hook - uses pure function
106
+ */
107
+ add_filter('woocommerce_product_price', function($price, $product) {
108
+ if (!is_user_logged_in()) {
109
+ return $price;
110
+ }
111
+
112
+ $user_id = get_current_user_id();
113
+ $tier = get_user_meta($user_id, 'membership_tier', true);
114
+ $member_since = get_user_meta($user_id, 'member_since', true);
115
+ $days_member = (time() - strtotime($member_since)) / DAY_IN_SECONDS;
116
+
117
+ // Pure function call - easily testable
118
+ return BusinessLogic\calculate_discount($price, $tier, $days_member);
119
+ }, 10, 2);
120
+
121
+ /**
122
+ * WordPress action hook - handles side effects with security
123
+ */
124
+ add_action('wp_ajax_upgrade_membership', function() {
125
+ // 1. Security first - capability check
126
+ if (!current_user_can('edit_user')) {
127
+ wp_send_json_error('Insufficient permissions', 403);
128
+ }
129
+
130
+ // 2. Security first - nonce verification
131
+ check_ajax_referer('upgrade_membership', 'nonce');
132
+
133
+ // 3. Sanitize inputs
134
+ $user_id = absint($_POST['user_id']);
135
+ $new_tier = sanitize_text_field($_POST['new_tier']);
136
+
137
+ // 4. Get current data (side effect)
138
+ $current_tier = get_user_meta($user_id, 'membership_tier', true);
139
+
140
+ // 5. Use pure function for validation
141
+ $validation = BusinessLogic\validate_tier_upgrade($current_tier, $new_tier);
142
+
143
+ if (!$validation['valid']) {
144
+ wp_send_json_error($validation['error']);
145
+ }
146
+
147
+ // 6. Update database (side effect)
148
+ update_user_meta($user_id, 'membership_tier', $new_tier);
149
+ update_user_meta($user_id, 'tier_upgraded_at', current_time('mysql'));
150
+
151
+ // 7. Send response (escaped)
152
+ wp_send_json_success([
153
+ 'message' => 'Membership upgraded successfully',
154
+ 'new_tier' => esc_html($new_tier)
155
+ ]);
156
+ });
157
+ ```
158
+
159
+ ---
160
+
161
+ ## Function Factory Pattern
162
+
163
+ **Pre-compile configuration for performance.**
164
+
165
+ ```php
166
+ <?php
167
+ namespace MyPlugin\Pure;
168
+
169
+ /**
170
+ * Function factory: Pre-compile email validator
171
+ * @pure - Configuration captured in closure
172
+ */
173
+ function create_email_validator(
174
+ array $bad_domains,
175
+ array $typo_corrections
176
+ ): callable {
177
+ // Configuration pre-compiled once during factory creation
178
+ return function (string $email) use ($bad_domains, $typo_corrections): array {
179
+ return validate_email_domain($email, $bad_domains, $typo_corrections);
180
+ };
181
+ }
182
+
183
+ /**
184
+ * Validate email domain
185
+ * @pure - Deterministic, no WordPress dependencies
186
+ */
187
+ function validate_email_domain(
188
+ string $email,
189
+ array $bad_domains,
190
+ array $typo_domains
191
+ ): array {
192
+ if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
193
+ return ['valid' => false, 'error' => 'Invalid email format'];
194
+ }
195
+
196
+ $domain = strtolower(substr($email, strpos($email, '@') + 1));
197
+
198
+ if (in_array($domain, $bad_domains, true)) {
199
+ return ['valid' => false, 'error' => 'Disposable email domain'];
200
+ }
201
+
202
+ if (isset($typo_domains[$domain])) {
203
+ return [
204
+ 'valid' => false,
205
+ 'error' => 'Possible typo',
206
+ 'suggestion' => $typo_domains[$domain]
207
+ ];
208
+ }
209
+
210
+ return ['valid' => true];
211
+ }
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Production Example: Email Validator
217
+
218
+ **From ima-espo plugin - 130 tests, <30ms execution.**
219
+
220
+ ```php
221
+ <?php
222
+ use function MyPlugin\Pure\create_email_validator;
223
+
224
+ /**
225
+ * WordPress wrapper class using function factory pattern
226
+ */
227
+ class EmailValidatorCore {
228
+ protected $validator = null;
229
+ protected $bad_domains = [];
230
+ protected $typo_domains = [];
231
+
232
+ /**
233
+ * Constructor: Pre-compile validator function once
234
+ */
235
+ public function __construct(array $bad_domains = [], array $typo_domains = []) {
236
+ $this->bad_domains = $bad_domains;
237
+ $this->typo_domains = $typo_domains;
238
+
239
+ // Function factory: Configuration pre-compiled once
240
+ // Performance: 2-5x speedup when validating multiple emails
241
+ $this->validator = create_email_validator($bad_domains, $typo_domains);
242
+ }
243
+
244
+ /**
245
+ * WordPress integration method
246
+ */
247
+ public function validate_email_domain(string $email) {
248
+ // Security: Sanitize input
249
+ $email = sanitize_email($email);
250
+
251
+ // Use pre-compiled validator
252
+ $result = ($this->validator)($email);
253
+
254
+ // WordPress integration: Log failures in debug mode
255
+ if (!$result['valid'] && defined('WP_DEBUG') && WP_DEBUG) {
256
+ error_log(sprintf('[Plugin] Email validation failed: %s - %s', $email, $result['error']));
257
+ }
258
+
259
+ return $result;
260
+ }
261
+
262
+ /**
263
+ * Allow customization via WordPress filters
264
+ */
265
+ public function get_bad_domains(): array {
266
+ return apply_filters('my_plugin_bad_email_domains', $this->bad_domains);
267
+ }
268
+ }
269
+ ```
270
+
271
+ ### Benefits
272
+ - **Performance**: 2-5x faster (configuration pre-compiled once)
273
+ - **Testability**: Pure functions fully testable without WordPress
274
+ - **Security**: Sanitization at wrapper boundary
275
+ - **Extensibility**: WordPress filters allow customization