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.
- package/LICENSE +21 -0
- package/README.md +463 -0
- package/dist/cli.js +1064 -0
- package/package.json +49 -0
- package/platforms/claude/adapter.ts +115 -0
- package/platforms/junie/adapter.ts +254 -0
- package/platforms/junie/agents-template.md +113 -0
- package/platforms/junie/hook-translations.md +84 -0
- package/platforms/shared/detector.ts +27 -0
- package/platforms/shared/installer.ts +202 -0
- package/platforms/shared/types.ts +78 -0
- package/plugins/ima-claude/.claude-plugin/plugin.json +25 -0
- package/plugins/ima-claude/agents/explorer.md +30 -0
- package/plugins/ima-claude/agents/implementer.md +30 -0
- package/plugins/ima-claude/agents/memory.md +42 -0
- package/plugins/ima-claude/agents/reviewer.md +53 -0
- package/plugins/ima-claude/agents/tester.md +33 -0
- package/plugins/ima-claude/agents/wp-developer.md +46 -0
- package/plugins/ima-claude/hooks/README.md +145 -0
- package/plugins/ima-claude/hooks/atlassian_prereqs.py +112 -0
- package/plugins/ima-claude/hooks/block_sed_edits.py +59 -0
- package/plugins/ima-claude/hooks/bootstrap.sh +90 -0
- package/plugins/ima-claude/hooks/bootstrap_utility_check.py +94 -0
- package/plugins/ima-claude/hooks/composer_autoload_check.py +70 -0
- package/plugins/ima-claude/hooks/docs_organization.py +104 -0
- package/plugins/ima-claude/hooks/enforce_rg_over_grep.py +56 -0
- package/plugins/ima-claude/hooks/fp_utility_check.py +90 -0
- package/plugins/ima-claude/hooks/hook_logger.py +69 -0
- package/plugins/ima-claude/hooks/hooks.json +239 -0
- package/plugins/ima-claude/hooks/jira_issue_fetch.py +79 -0
- package/plugins/ima-claude/hooks/jquery_in_wordpress.py +92 -0
- package/plugins/ima-claude/hooks/memory_bootstrap.py +79 -0
- package/plugins/ima-claude/hooks/memory_store_reminder.py +75 -0
- package/plugins/ima-claude/hooks/prompt_coach.py +125 -0
- package/plugins/ima-claude/hooks/prompt_coach_digest.md +48 -0
- package/plugins/ima-claude/hooks/prompt_coach_system.md +30 -0
- package/plugins/ima-claude/hooks/sequential_thinking_check.py +81 -0
- package/plugins/ima-claude/hooks/serena_over_grep.py +96 -0
- package/plugins/ima-claude/hooks/serena_over_read.py +66 -0
- package/plugins/ima-claude/hooks/serena_project_check.py +133 -0
- package/plugins/ima-claude/hooks/sql_injection_check.py +73 -0
- package/plugins/ima-claude/hooks/task_master_after_plan.py +31 -0
- package/plugins/ima-claude/hooks/task_master_before_impl.py +93 -0
- package/plugins/ima-claude/hooks/tavily_extract_advanced.py +48 -0
- package/plugins/ima-claude/hooks/vestige_before_external.py +86 -0
- package/plugins/ima-claude/hooks/webfetch_to_tavily.py +42 -0
- package/plugins/ima-claude/hooks/websearch_to_tavily.py +41 -0
- package/plugins/ima-claude/hooks/wp_security_check.py +150 -0
- package/plugins/ima-claude/personalities/README.md +45 -0
- package/plugins/ima-claude/personalities/enable-40k.md +69 -0
- package/plugins/ima-claude/personalities/enable-templars.md +69 -0
- package/plugins/ima-claude/skills/.research-summary.md +340 -0
- package/plugins/ima-claude/skills/architect/SKILL.md +304 -0
- package/plugins/ima-claude/skills/compound-bridge/SKILL.md +200 -0
- package/plugins/ima-claude/skills/discourse/SKILL.md +440 -0
- package/plugins/ima-claude/skills/discourse-admin/SKILL.md +192 -0
- package/plugins/ima-claude/skills/discourse-admin/references/api-endpoints.md +441 -0
- package/plugins/ima-claude/skills/discourse-admin/references/gotchas.md +107 -0
- package/plugins/ima-claude/skills/discourse-admin/references/staging-defaults.md +98 -0
- package/plugins/ima-claude/skills/discourse-admin/scripts/discourse-admin.py +319 -0
- package/plugins/ima-claude/skills/docs-organize/SKILL.md +254 -0
- package/plugins/ima-claude/skills/docs-organize/templates/active-README.md +50 -0
- package/plugins/ima-claude/skills/docs-organize/templates/archive-README.md +57 -0
- package/plugins/ima-claude/skills/docs-organize/templates/docs-README.md +43 -0
- package/plugins/ima-claude/skills/docs-organize/templates/phase-archive-README.md +83 -0
- package/plugins/ima-claude/skills/docs-organize/templates/section-README.md +48 -0
- package/plugins/ima-claude/skills/docs-organize/templates/transient-README.md +79 -0
- package/plugins/ima-claude/skills/docs-organize/templates/transient-gitignore +9 -0
- package/plugins/ima-claude/skills/ember-discourse/SKILL.md +496 -0
- package/plugins/ima-claude/skills/functional-programmer/SKILL.md +258 -0
- package/plugins/ima-claude/skills/ima-bootstrap/SKILL.md +278 -0
- package/plugins/ima-claude/skills/ima-bootstrap/references/bootstrap-patterns.md +356 -0
- package/plugins/ima-claude/skills/ima-bootstrap/references/ima-brand.md +273 -0
- package/plugins/ima-claude/skills/ima-bootstrap/references/theme-integration.md +212 -0
- package/plugins/ima-claude/skills/ima-brand/SKILL.md +108 -0
- package/plugins/ima-claude/skills/ima-brand/references/brand-identity.md +140 -0
- package/plugins/ima-claude/skills/ima-brand/references/digital-standards.md +180 -0
- package/plugins/ima-claude/skills/ima-brand/references/visual-system.md +173 -0
- package/plugins/ima-claude/skills/ima-forms-expert/SKILL.md +175 -0
- package/plugins/ima-claude/skills/ima-forms-expert/references/container-components.md +154 -0
- package/plugins/ima-claude/skills/ima-forms-expert/references/examples.md +328 -0
- package/plugins/ima-claude/skills/ima-forms-expert/references/field-components.md +298 -0
- package/plugins/ima-claude/skills/ima-forms-expert/references/form-factory.md +193 -0
- package/plugins/ima-claude/skills/ima-forms-expert/references/quick-reference.md +153 -0
- package/plugins/ima-claude/skills/ima-forms-expert/references/validation-engine.md +336 -0
- package/plugins/ima-claude/skills/jira-checkpoint/SKILL.md +178 -0
- package/plugins/ima-claude/skills/jquery/SKILL.md +413 -0
- package/plugins/ima-claude/skills/js-fp/SKILL.md +463 -0
- package/plugins/ima-claude/skills/js-fp/core-principles.md +487 -0
- package/plugins/ima-claude/skills/js-fp/examples/pure-functions.js +260 -0
- package/plugins/ima-claude/skills/js-fp/examples/tests/pure-functions.test.js +262 -0
- package/plugins/ima-claude/skills/js-fp/references/anti-patterns.md +120 -0
- package/plugins/ima-claude/skills/js-fp/references/performance-patterns.md +116 -0
- package/plugins/ima-claude/skills/js-fp/references/testing-patterns.md +134 -0
- package/plugins/ima-claude/skills/js-fp-api/SKILL.md +280 -0
- package/plugins/ima-claude/skills/js-fp-api/examples/crud-endpoint.js +258 -0
- package/plugins/ima-claude/skills/js-fp-api/references/middleware-patterns.md +134 -0
- package/plugins/ima-claude/skills/js-fp-api/references/security-sql.md +110 -0
- package/plugins/ima-claude/skills/js-fp-api/references/validation-patterns.md +165 -0
- package/plugins/ima-claude/skills/js-fp-react/SKILL.md +447 -0
- package/plugins/ima-claude/skills/js-fp-react/examples/ProductCard.tsx +65 -0
- package/plugins/ima-claude/skills/js-fp-react/references/hooks-advanced.md +136 -0
- package/plugins/ima-claude/skills/js-fp-react/references/performance-patterns.md +175 -0
- package/plugins/ima-claude/skills/js-fp-vue/SKILL.md +322 -0
- package/plugins/ima-claude/skills/js-fp-vue/references/complete-examples.md +397 -0
- package/plugins/ima-claude/skills/js-fp-vue/references/composables-advanced.md +282 -0
- package/plugins/ima-claude/skills/js-fp-vue/references/reactivity-patterns.md +348 -0
- package/plugins/ima-claude/skills/js-fp-vue/references/testing.md +314 -0
- package/plugins/ima-claude/skills/js-fp-wordpress/SKILL.md +301 -0
- package/plugins/ima-claude/skills/js-fp-wordpress/references/ajax-patterns.md +192 -0
- package/plugins/ima-claude/skills/js-fp-wordpress/references/event-patterns.md +136 -0
- package/plugins/ima-claude/skills/js-fp-wordpress/references/wp-integration.md +248 -0
- package/plugins/ima-claude/skills/livecanvas/SKILL.md +209 -0
- package/plugins/ima-claude/skills/livecanvas/references/livecanvas-features.md +311 -0
- package/plugins/ima-claude/skills/livecanvas/references/loops-and-logic.md +730 -0
- package/plugins/ima-claude/skills/livecanvas/references/picostrap.md +227 -0
- package/plugins/ima-claude/skills/mcp-atlassian/SKILL.md +339 -0
- package/plugins/ima-claude/skills/mcp-context7/SKILL.md +109 -0
- package/plugins/ima-claude/skills/mcp-memory/SKILL.md +182 -0
- package/plugins/ima-claude/skills/mcp-qdrant/SKILL.md +233 -0
- package/plugins/ima-claude/skills/mcp-sequential/SKILL.md +149 -0
- package/plugins/ima-claude/skills/mcp-serena/SKILL.md +174 -0
- package/plugins/ima-claude/skills/mcp-tavily/SKILL.md +118 -0
- package/plugins/ima-claude/skills/mcp-vestige/SKILL.md +259 -0
- package/plugins/ima-claude/skills/php-authnet/SKILL.md +275 -0
- package/plugins/ima-claude/skills/php-authnet/references/api-reference.md +624 -0
- package/plugins/ima-claude/skills/php-authnet/references/sandbox-testing.md +424 -0
- package/plugins/ima-claude/skills/php-fp/SKILL.md +333 -0
- package/plugins/ima-claude/skills/php-fp/examples/pure-functions.php +403 -0
- package/plugins/ima-claude/skills/php-fp/examples/tests/PureFunctionsTest.php +515 -0
- package/plugins/ima-claude/skills/php-fp/references/core-principles.md +277 -0
- package/plugins/ima-claude/skills/php-fp/references/testing-patterns.md +374 -0
- package/plugins/ima-claude/skills/php-fp-wordpress/SKILL.md +216 -0
- package/plugins/ima-claude/skills/php-fp-wordpress/references/fp-patterns.md +275 -0
- package/plugins/ima-claude/skills/php-fp-wordpress/references/plugin-architecture.md +295 -0
- package/plugins/ima-claude/skills/php-fp-wordpress/references/security-examples.md +203 -0
- package/plugins/ima-claude/skills/php-fp-wordpress/references/testing-strategy.md +259 -0
- package/plugins/ima-claude/skills/phpunit-wp/SKILL.md +716 -0
- package/plugins/ima-claude/skills/playwright/SKILL.md +434 -0
- package/plugins/ima-claude/skills/playwright/references/accessibility-testing.md +153 -0
- package/plugins/ima-claude/skills/playwright/references/ci-cd.md +268 -0
- package/plugins/ima-claude/skills/playwright/references/network-mocking.md +270 -0
- package/plugins/ima-claude/skills/playwright/references/visual-regression.md +215 -0
- package/plugins/ima-claude/skills/py-fp/SKILL.md +663 -0
- package/plugins/ima-claude/skills/py-fp/examples/pure-functions.py +185 -0
- package/plugins/ima-claude/skills/py-fp/examples/tests/test_pure_functions.py +244 -0
- package/plugins/ima-claude/skills/py-fp/references/core-principles.md +381 -0
- package/plugins/ima-claude/skills/py-fp/references/testing-patterns.md +283 -0
- package/plugins/ima-claude/skills/quasar-fp/SKILL.md +327 -0
- package/plugins/ima-claude/skills/quasar-fp/metadata.json +85 -0
- package/plugins/ima-claude/skills/quasar-fp/references/component-patterns.md +257 -0
- package/plugins/ima-claude/skills/quasar-fp/references/theme-integration.md +233 -0
- package/plugins/ima-claude/skills/quasar-fp/references/utility-classes.md +237 -0
- package/plugins/ima-claude/skills/quickstart/SKILL.md +129 -0
- package/plugins/ima-claude/skills/rails/SKILL.md +359 -0
- package/plugins/ima-claude/skills/resume-session/SKILL.md +68 -0
- package/plugins/ima-claude/skills/rg/SKILL.md +205 -0
- package/plugins/ima-claude/skills/ruby-fp/SKILL.md +336 -0
- package/plugins/ima-claude/skills/save-session/SKILL.md +81 -0
- package/plugins/ima-claude/skills/scorecard/SKILL.md +96 -0
- package/plugins/ima-claude/skills/skill-analyzer/SKILL.md +127 -0
- package/plugins/ima-claude/skills/skill-analyzer/references/advanced-checklist.md +44 -0
- package/plugins/ima-claude/skills/skill-analyzer/references/core-checklist.md +60 -0
- package/plugins/ima-claude/skills/skill-analyzer/scripts/analyze_skill.py +418 -0
- package/plugins/ima-claude/skills/skill-creator/LICENSE.txt +202 -0
- package/plugins/ima-claude/skills/skill-creator/SKILL.md +343 -0
- package/plugins/ima-claude/skills/skill-creator/references/output-patterns.md +82 -0
- package/plugins/ima-claude/skills/skill-creator/references/workflows.md +28 -0
- package/plugins/ima-claude/skills/skill-creator/scripts/init_skill.py +303 -0
- package/plugins/ima-claude/skills/skill-creator/scripts/package_skill.py +110 -0
- package/plugins/ima-claude/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/plugins/ima-claude/skills/task-master/SKILL.md +51 -0
- package/plugins/ima-claude/skills/task-planner/SKILL.md +228 -0
- package/plugins/ima-claude/skills/task-runner/SKILL.md +192 -0
- package/plugins/ima-claude/skills/unit-testing/SKILL.md +198 -0
- package/plugins/ima-claude/skills/unit-testing/references/mock-patterns.md +181 -0
- package/plugins/ima-claude/skills/unit-testing/references/tdd-workflow.md +177 -0
- package/plugins/ima-claude/skills/unit-testing/references/test-strategy.md +126 -0
- package/plugins/ima-claude/skills/wp-local/SKILL.md +246 -0
- package/plugins/ima-claude/skills/wp-local/references/configuration.md +198 -0
- package/plugins/ima-claude/skills/wp-local/references/wp-cli-reference.md +406 -0
- package/plugins/ima-claude/skills/wp-local/scripts/wp-local.sh +61 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "php-fp"
|
|
3
|
+
description: "Core FP principles with anti-over-engineering focus - Simple > Complex | Evidence > Assumptions"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PHP Functional Programming
|
|
7
|
+
|
|
8
|
+
Core functional programming principles for PHP with anti-over-engineering enforcement. This skill provides error-preventing essentials and references to deep-dive content.
|
|
9
|
+
|
|
10
|
+
## When to Use This Skill
|
|
11
|
+
|
|
12
|
+
- Implementing pure, testable PHP functions
|
|
13
|
+
- Need FP architectural guidance for PHP
|
|
14
|
+
- Preventing over-engineering and custom FP utility creation
|
|
15
|
+
- Comprehensive testing strategies with PHPUnit
|
|
16
|
+
- Evidence-based performance optimization
|
|
17
|
+
|
|
18
|
+
## CRITICAL: Anti-Over-Engineering (PRIMARY FOCUS)
|
|
19
|
+
|
|
20
|
+
**Core Principle**: "Simple > Complex | Evidence > Assumptions"
|
|
21
|
+
|
|
22
|
+
> **Clarification**: This skill prevents CREATING custom FP utility functions (pipe, compose, curry) to make PHP "feel" like Haskell. Using established libraries (Carbon, Collections, etc.) is perfectly fine. FP is a mindset—pure functions, immutability, composition—not a rigid API signature.
|
|
23
|
+
|
|
24
|
+
### Don't Create Custom FP Utilities
|
|
25
|
+
|
|
26
|
+
```php
|
|
27
|
+
<?php
|
|
28
|
+
// DON'T CREATE: pipe() utility
|
|
29
|
+
function pipe(...$functions) {
|
|
30
|
+
return fn($value) => array_reduce($functions, fn($carry, $fn) => $fn($carry), $value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// INSTEAD: Native early returns
|
|
34
|
+
function validateUser(array $userData): array {
|
|
35
|
+
$requiredCheck = validateRequired(['email', 'name'], $userData);
|
|
36
|
+
if (!$requiredCheck['valid']) return $requiredCheck;
|
|
37
|
+
return validateEmail($userData);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// DON'T CREATE: curry() utility
|
|
41
|
+
// INSTEAD: Native closures
|
|
42
|
+
function createValidator(array $rules): callable {
|
|
43
|
+
return fn($value): array => ['valid' => empty(array_filter($rules, fn($r) => !$r['validator']($value)))];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// DON'T CREATE: Complex monad implementations
|
|
47
|
+
// INSTEAD: Simple result arrays
|
|
48
|
+
function divide(float $a, float $b): array {
|
|
49
|
+
return $b === 0.0 ? ['success' => false, 'error' => 'Division by zero'] : ['success' => true, 'data' => $a / $b];
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### The 4-Question Quality Framework
|
|
54
|
+
|
|
55
|
+
Before extracting or abstracting, ask:
|
|
56
|
+
|
|
57
|
+
1. **"Can this be pure?"** - Separate business logic from side effects
|
|
58
|
+
2. **"Can this use native patterns?"** - Avoid creating custom FP utilities, use PHP features
|
|
59
|
+
3. **"Can this be simplified?"** - Choose simple solution over complex abstraction
|
|
60
|
+
4. **"Is this complexity justified?"** - Evidence-based complexity decisions
|
|
61
|
+
|
|
62
|
+
### When NOT to Extract: WordPress Example
|
|
63
|
+
|
|
64
|
+
**Context**: CRMAPI class sends webhook data via HTTP POST.
|
|
65
|
+
|
|
66
|
+
**Analysis**: Applied 4-question framework - NO pure function extraction needed.
|
|
67
|
+
|
|
68
|
+
- `sanitize_data()` uses `sanitize_text_field()` which applies WordPress filters - NOT PURE
|
|
69
|
+
- `send_api_request()` uses WordPress HTTP API - NATIVE PATTERNS ALREADY
|
|
70
|
+
- Current structure: 239 lines, ~35 lines of logic - ALREADY SIMPLE
|
|
71
|
+
- Extraction would add indirection without benefits - NOT JUSTIFIED
|
|
72
|
+
|
|
73
|
+
**Result**: Grade B+ (Appropriate WordPress Wrapper). Don't extract pure functions when WordPress integration IS the business logic.
|
|
74
|
+
|
|
75
|
+
### Context-Appropriate Complexity
|
|
76
|
+
|
|
77
|
+
```php
|
|
78
|
+
<?php
|
|
79
|
+
// CLI Script: Simple and direct
|
|
80
|
+
function processFile(string $filePath): array {
|
|
81
|
+
$data = file_get_contents($filePath);
|
|
82
|
+
return array_map('strtoupper', array_filter(explode("\n", $data), fn($l) => trim($l) !== ''));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Production Service: Appropriate error handling
|
|
86
|
+
function processFile(string $filePath, LoggerInterface $logger): array {
|
|
87
|
+
try {
|
|
88
|
+
if (!file_exists($filePath)) throw new InvalidArgumentException("File not found: {$filePath}");
|
|
89
|
+
$lines = array_filter(explode("\n", file_get_contents($filePath)), fn($l) => trim($l) !== '');
|
|
90
|
+
$logger->info('File processed', ['path' => $filePath, 'lines' => count($lines)]);
|
|
91
|
+
return ['success' => true, 'data' => array_map('strtoupper', $lines)];
|
|
92
|
+
} catch (Exception $e) {
|
|
93
|
+
$logger->error('File processing failed', ['path' => $filePath, 'error' => $e->getMessage()]);
|
|
94
|
+
return ['success' => false, 'error' => $e->getMessage()];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Core FP Patterns (Quick Reference)
|
|
100
|
+
|
|
101
|
+
### 1. Purity and Side Effect Isolation
|
|
102
|
+
|
|
103
|
+
```php
|
|
104
|
+
<?php
|
|
105
|
+
declare(strict_types=1);
|
|
106
|
+
|
|
107
|
+
// PURE: business logic
|
|
108
|
+
function calculateTotal(array $items): float {
|
|
109
|
+
return array_reduce($items, fn($sum, $item) => $sum + $item['price'], 0.0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ISOLATED: side effects separate
|
|
113
|
+
function logAndCalculate(array $items, LoggerInterface $logger): float {
|
|
114
|
+
$total = calculateTotal($items);
|
|
115
|
+
$logger->info("Total: {$total}");
|
|
116
|
+
return $total;
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 2. Composition Over Inheritance
|
|
121
|
+
|
|
122
|
+
```php
|
|
123
|
+
<?php
|
|
124
|
+
// Simple validators that compose
|
|
125
|
+
function validateRequired($value): bool { return $value !== null && $value !== ''; }
|
|
126
|
+
function validateEmail(string $value): bool { return filter_var($value, FILTER_VALIDATE_EMAIL) !== false; }
|
|
127
|
+
function validateLength(int $min, int $max): callable {
|
|
128
|
+
return fn(string $value): bool => strlen($value) >= $min && strlen($value) <= $max;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Composition without utilities
|
|
132
|
+
function validateUserEmail(string $email): array {
|
|
133
|
+
if (!validateRequired($email)) return ['valid' => false, 'error' => 'Required'];
|
|
134
|
+
if (!validateEmail($email)) return ['valid' => false, 'error' => 'Invalid email'];
|
|
135
|
+
if (!validateLength(5, 100)($email)) return ['valid' => false, 'error' => 'Length'];
|
|
136
|
+
return ['valid' => true];
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 3. Dependency Injection
|
|
141
|
+
|
|
142
|
+
```php
|
|
143
|
+
<?php
|
|
144
|
+
// Explicit dependencies, fully testable
|
|
145
|
+
function saveUser(array $userData, PasswordHasherInterface $hasher, DatabaseInterface $db): array {
|
|
146
|
+
return $db->save(['name' => $userData['name'], 'password' => $hasher->hash($userData['password'])]);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Service with constructor DI
|
|
150
|
+
class UserService {
|
|
151
|
+
public function __construct(
|
|
152
|
+
private readonly PasswordHasherInterface $hasher,
|
|
153
|
+
private readonly DatabaseInterface $db
|
|
154
|
+
) {}
|
|
155
|
+
|
|
156
|
+
public function saveUser(array $userData): array {
|
|
157
|
+
return saveUser($userData, $this->hasher, $this->db);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### 4. Immutability
|
|
163
|
+
|
|
164
|
+
```php
|
|
165
|
+
<?php
|
|
166
|
+
// Always return new arrays
|
|
167
|
+
function updateUserSettings(array $user, array $settings): array {
|
|
168
|
+
return [...$user, 'settings' => array_merge($user['settings'] ?? [], $settings), 'updated_at' => time()];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function addItem(array $items, array $newItem): array { return [...$items, $newItem]; }
|
|
172
|
+
function removeItem(array $items, int $id): array { return array_values(array_filter($items, fn($i) => $i['id'] !== $id)); }
|
|
173
|
+
function updateItem(array $items, int $id, array $updates): array {
|
|
174
|
+
return array_map(fn($i) => $i['id'] === $id ? [...$i, ...$updates] : $i, $items);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## PHP-Specific Patterns
|
|
179
|
+
|
|
180
|
+
### Native Array Functions + Strict Types (MANDATORY)
|
|
181
|
+
|
|
182
|
+
```php
|
|
183
|
+
<?php
|
|
184
|
+
declare(strict_types=1);
|
|
185
|
+
|
|
186
|
+
// Native array methods over loops
|
|
187
|
+
function processUsers(array $users): array {
|
|
188
|
+
return array_slice(
|
|
189
|
+
array_map(fn($u) => [...$u, 'display_name' => "{$u['first_name']} {$u['last_name']}"],
|
|
190
|
+
array_filter($users, fn($u) => $u['active'])),
|
|
191
|
+
0, 10
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Match expressions (PHP 8.0+)
|
|
196
|
+
function getTierDiscount(string $tier): float {
|
|
197
|
+
return match($tier) {
|
|
198
|
+
'bronze' => 0.05, 'silver' => 0.10, 'gold' => 0.15, 'platinum' => 0.20, default => 0.0
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Union types (PHP 8.0+)
|
|
203
|
+
function processResult(array|false $result): array {
|
|
204
|
+
return $result === false ? ['success' => false, 'error' => 'Not found'] : ['success' => true, 'data' => $result];
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Result Type Pattern
|
|
209
|
+
|
|
210
|
+
```php
|
|
211
|
+
<?php
|
|
212
|
+
// Standard result shape
|
|
213
|
+
function createResult($data = null, ?string $error = null): array {
|
|
214
|
+
return $error !== null ? ['success' => false, 'error' => $error] : ['success' => true, 'data' => $data];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Chain results with early return
|
|
218
|
+
function calculate(float $a, float $b, float $c): array {
|
|
219
|
+
$r1 = divide($a, $b);
|
|
220
|
+
if (!$r1['success']) return $r1;
|
|
221
|
+
return divide($r1['data'], $c);
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
> **Deep dive**: See `references/core-principles.md` for complete Result Type patterns and error handling strategies.
|
|
226
|
+
|
|
227
|
+
## Testing Essentials
|
|
228
|
+
|
|
229
|
+
Pure functions enable testing ALL edge cases systematically.
|
|
230
|
+
|
|
231
|
+
```php
|
|
232
|
+
<?php
|
|
233
|
+
use PHPUnit\Framework\TestCase;
|
|
234
|
+
|
|
235
|
+
class CalculatorTest extends TestCase {
|
|
236
|
+
/**
|
|
237
|
+
* @dataProvider discountProvider
|
|
238
|
+
*/
|
|
239
|
+
public function testCalculateDiscount(float $price, float $rate, float $expected): void {
|
|
240
|
+
$this->assertEquals($expected, calculateDiscount($price, $rate));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
public function discountProvider(): array {
|
|
244
|
+
return [
|
|
245
|
+
'standard' => [100.0, 0.1, 90.0],
|
|
246
|
+
'zero' => [100.0, 0.0, 100.0],
|
|
247
|
+
'full' => [100.0, 1.0, 0.0],
|
|
248
|
+
];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
> **Deep dive**: See `references/testing-patterns.md` for comprehensive PHPUnit strategies, edge case patterns, mocking, and test organization.
|
|
254
|
+
|
|
255
|
+
## Performance Patterns (Evidence-Based)
|
|
256
|
+
|
|
257
|
+
Optimize only when needed with evidence. Key pattern: **Configuration Pre-Compilation**.
|
|
258
|
+
|
|
259
|
+
```php
|
|
260
|
+
<?php
|
|
261
|
+
// Problem: O(records x config) - config accessed every iteration
|
|
262
|
+
// Solution: Pre-compile configuration once
|
|
263
|
+
|
|
264
|
+
function createRecordProcessor(array $schema): callable {
|
|
265
|
+
// Setup once
|
|
266
|
+
$fieldProcessors = array_map(fn($f) => fn($v) => transformField($v, $f['type']), $schema['fields']);
|
|
267
|
+
|
|
268
|
+
return function(array $record) use ($schema, $fieldProcessors): array {
|
|
269
|
+
$result = [];
|
|
270
|
+
foreach ($schema['fields'] as $i => $field) {
|
|
271
|
+
$result[$field['name']] = $fieldProcessors[$i]($record[$field['name']]);
|
|
272
|
+
}
|
|
273
|
+
return $result;
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
$processor = createRecordProcessor($schema); // Setup phase
|
|
278
|
+
$results = array_map($processor, $records); // Linear execution
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**Real-world result**: Email validation in ima-espo achieved 2-5x speedup with function factory pattern. 130 tests, 236 assertions, <30ms total.
|
|
282
|
+
|
|
283
|
+
## Quality Gates Checklist
|
|
284
|
+
|
|
285
|
+
Before implementation:
|
|
286
|
+
|
|
287
|
+
1. **"Can this be pure?"** - Separate business logic from side effects
|
|
288
|
+
2. **"Can this use native patterns?"** - Avoid creating custom FP utilities
|
|
289
|
+
3. **"Can this be simplified?"** - Simple > complex
|
|
290
|
+
4. **"Is this complexity justified?"** - Evidence required
|
|
291
|
+
5. **"Is this testable?"** - Pure functions enable comprehensive testing
|
|
292
|
+
6. **"Are strict types used?"** - `declare(strict_types=1)` at file top
|
|
293
|
+
|
|
294
|
+
## When to Load Reference Files
|
|
295
|
+
|
|
296
|
+
### Deep Principles and Explanations
|
|
297
|
+
**File**: `references/core-principles.md`
|
|
298
|
+
**Load when**:
|
|
299
|
+
- Learning mode or explaining WHY behind patterns
|
|
300
|
+
- Making architectural decisions
|
|
301
|
+
- Need complete Result Type patterns
|
|
302
|
+
- Anti-pattern recognition details
|
|
303
|
+
- Cross-pattern comparisons
|
|
304
|
+
|
|
305
|
+
### Testing Methodology
|
|
306
|
+
**File**: `references/testing-patterns.md`
|
|
307
|
+
**Load when**:
|
|
308
|
+
- Building comprehensive test suites
|
|
309
|
+
- Improving test coverage
|
|
310
|
+
- Edge case analysis and boundary testing
|
|
311
|
+
- Setting up mocking strategies
|
|
312
|
+
- Performance testing pure functions
|
|
313
|
+
|
|
314
|
+
### Working Examples
|
|
315
|
+
**Directory**: `examples/`
|
|
316
|
+
**Load when**:
|
|
317
|
+
- Need complete working code
|
|
318
|
+
- Integration examples
|
|
319
|
+
- Learning implementation patterns
|
|
320
|
+
|
|
321
|
+
## Integration with Domain Skills
|
|
322
|
+
|
|
323
|
+
This core skill provides the foundation for:
|
|
324
|
+
|
|
325
|
+
- **php-fp-wordpress**: WordPress patterns with FP principles
|
|
326
|
+
- **php-fp-laravel**: Laravel patterns with FP principles (future)
|
|
327
|
+
- **php-fp-symfony**: Symfony patterns with FP principles (future)
|
|
328
|
+
|
|
329
|
+
Each domain skill references this core and adds domain-specific patterns.
|
|
330
|
+
|
|
331
|
+
## Philosophy
|
|
332
|
+
|
|
333
|
+
*"Pure functions, native PHP patterns, strict types, appropriate complexity, and comprehensive testing for maintainable, predictable code that respects the language and solves real problems simply."*
|