|
1 | | -# StringManipulation Development Guide |
2 | | - |
3 | | -## Critical Development Rules |
4 | | -- **ALWAYS run all tests before committing**: `docker-compose run --rm test-all` |
5 | | -- **NEVER force push or use --force with git commands** |
6 | | -- **NEVER ignore test failures or errors** |
7 | | -- **ALWAYS use conventional commit messages** (feat:, fix:, chore:, etc.) |
8 | | -- **NEVER overwrite or amend existing commit messages** |
9 | | - |
10 | | -## Build & Testing Commands |
11 | | - |
12 | | -### Docker (Recommended - PHP 8.3 with AST extension) |
13 | | -**IMPORTANT**: Always use Docker for testing to ensure consistent environment with PHP 8.3 and AST extension. |
14 | | - |
15 | | -- Run all tests: `docker-compose run --rm test-all` |
16 | | -- Run Pest tests: `docker-compose run --rm tests ./vendor/bin/pest` |
17 | | -- Run single test: `docker-compose run --rm tests ./vendor/bin/pest --filter testName` |
18 | | -- Code style check: `docker-compose run --rm test-code-style` |
19 | | -- Static analysis: |
20 | | - - PHPStan: `docker-compose run --rm test-phpstan` |
21 | | - - Psalm: `docker-compose run --rm test-psalm` |
22 | | - - Phan: `docker-compose run --rm test-phan` |
23 | | -- PHP Mess Detector: `docker-compose run --rm test-phpmd` |
24 | | -- Mutation testing: `docker-compose run --rm test-infection` |
25 | | -- Code refactoring: `docker-compose run --rm test-rector` |
26 | | -- Linting: `docker-compose run --rm test-lint` |
27 | | -- Security check: `docker-compose run --rm test-security` |
28 | | - |
29 | | -### Local (Requires PHP 8.3+ with AST extension) |
30 | | -- Run all tests: `composer tests` |
31 | | -- Run Pest tests: `./vendor/bin/pest` |
32 | | -- Run single test: `./vendor/bin/pest --filter testName` |
33 | | -- Code style check: `composer test:code-style` |
34 | | -- Static analysis: `composer test:phpstan`, `composer test:psalm`, `composer test:phan` |
35 | | -- Linting: `composer test:lint` |
36 | | -- Mess detection: `composer test:phpmd` |
37 | | - |
38 | | -### Code Review |
39 | | -- CodeRabbit review: `coderabbit review --type committed --config .coderabbit.yaml --plain --base main` |
40 | | - - Reviews committed changes against main branch |
41 | | - - Uses project-specific configuration from .coderabbit.yaml |
42 | | - - Plain text output for terminal display |
43 | | - - Note: Can timeout if simout set too low; use 30 minute timeout |
44 | | - |
45 | | -## Code Style Guidelines |
46 | | -- PHP version: >=8.3.0 |
47 | | -- Strict typing required: `declare(strict_types=1);` |
48 | | -- Namespaces: PSR-4 `MarjovanLier\StringManipulation` |
49 | | -- Classes: Final, static methods preferred |
50 | | -- Class constants: Use typed constants (e.g., `private const array FOO = []`) |
51 | | -- Docblocks: Comprehensive for public methods with @param, @return and @example |
52 | | -- Parameter typing: Always explicit, including return types |
53 | | -- Type hints: Use PHP 8 attributes like `#[SensitiveParameter]` where appropriate |
54 | | -- Null handling: Explicit checks, optional parameters default to empty string |
55 | | -- Documentation: 100% method coverage with examples |
56 | | -- Standards: PSR guidelines with Laravel Pint (preset "per") |
57 | | -- Testing: Pest PHP with complete coverage |
58 | | -- PHPMD: Methods must not exceed 100 lines |
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +High-performance PHP 8.3+ string manipulation library with zero production dependencies. Single final class (`StringManipulation`) exposing static methods optimised with pre-computed character mappings for O(1) lookups via `strtr()`. |
| 8 | + |
| 9 | +## Build & Test Commands |
| 10 | + |
| 11 | +**Always use Docker** to ensure consistent PHP 8.3 + AST extension environment. |
| 12 | + |
| 13 | +| Task | Docker | Local | |
| 14 | +|------|--------|-------| |
| 15 | +| Full pipeline | `docker-compose run --rm test-all` | `composer tests` | |
| 16 | +| Pest tests | `docker-compose run --rm tests ./vendor/bin/pest` | `./vendor/bin/pest` | |
| 17 | +| Single test | `docker-compose run --rm tests ./vendor/bin/pest --filter testName` | `./vendor/bin/pest --filter testName` | |
| 18 | +| Code style check | `docker-compose run --rm test-code-style` | `composer test:code-style` | |
| 19 | +| Code style fix | `docker-compose run --rm tests ./vendor/bin/pint` | `composer fix:code-style` | |
| 20 | +| PHPStan | `docker-compose run --rm test-phpstan` | `composer test:phpstan` | |
| 21 | +| Psalm | `docker-compose run --rm test-psalm` | `composer test:psalm` | |
| 22 | +| Phan | `docker-compose run --rm test-phan` | `composer test:phan` | |
| 23 | +| PHPMD | `docker-compose run --rm test-phpmd` | `composer test:phpmd` | |
| 24 | +| Mutation testing | `docker-compose run --rm test-infection` | `composer test:infection` | |
| 25 | +| Rector (dry-run) | `docker-compose run --rm test-rector` | `composer test:rector` | |
| 26 | +| Linting | `docker-compose run --rm test-lint` | `composer test:lint` | |
| 27 | +| Security check | `docker-compose run --rm test-security` | `composer test:vulnerabilities-check` | |
| 28 | + |
| 29 | +**Run the full pipeline before committing**: `docker-compose run --rm test-all` |
| 30 | + |
| 31 | +## Architecture |
| 32 | + |
| 33 | +``` |
| 34 | +src/ |
| 35 | +├── StringManipulation.php # Single final class, all public static methods |
| 36 | +├── AccentNormalization.php # Trait: SEARCH_WORDS_MAPPING + ACCENT_MAPPING constants |
| 37 | +└── UnicodeMappings.php # Trait: UTF8_ANSI2 constant |
| 38 | +``` |
| 39 | + |
| 40 | +- **StringManipulation** uses two traits purely as constant containers for pre-computed character mapping arrays |
| 41 | +- All methods are static; the class is never instantiated |
| 42 | +- Performance comes from `strtr()` with pre-computed array constants (hash table O(1) lookups) and single-pass algorithms |
| 43 | +- The traits exist to keep the ~600 lines of mapping data separate from the ~400 lines of logic |
| 44 | + |
| 45 | +### Public API (7 methods) |
| 46 | + |
| 47 | +| Method | Purpose | |
| 48 | +|--------|---------| |
| 49 | +| `searchWords(?string)` | Normalise strings for database search (lowercase, remove accents/special chars) | |
| 50 | +| `nameFix(?string)` | Standardise surnames (handles mc/mac prefixes, van/von/de particles, hyphens) | |
| 51 | +| `removeAccents(string)` | Strip diacritics preserving case | |
| 52 | +| `utf8Ansi(?string)` | Convert UTF-8 to ANSI equivalents | |
| 53 | +| `isValidDate(string, string)` | Validate date string against format with logical checks | |
| 54 | +| `strReplace(...)` | Optimised replacement (uses `strtr()` for single-char) | |
| 55 | +| `trim(string, string)` | Stricter trim | |
| 56 | + |
| 57 | +## Static Analysis Levels |
| 58 | + |
| 59 | +All analysers run at their strictest settings: |
| 60 | +- **PHPStan**: Level MAX with strict rules, type-perfect, 95%+ type coverage |
| 61 | +- **Psalm**: Level 1, taint analysis enabled, 99.95% type coverage |
| 62 | +- **Phan**: All strict checking flags enabled, 11 quality plugins |
| 63 | +- **PHPMD**: Max 100 lines/method, max 15 public methods/class |
| 64 | + |
| 65 | +## Code Conventions |
| 66 | + |
| 67 | +- `declare(strict_types=1)` on every file |
| 68 | +- Final classes, static methods |
| 69 | +- Typed constants: `private const array NAME = []` |
| 70 | +- Comprehensive docblocks with `@param`, `@return`, `@example` on public methods |
| 71 | +- `#[\SensitiveParameter]` attribute on parameters containing personal data |
| 72 | +- Code style: Laravel Pint with PER (PHP Evolving Rules) preset |
| 73 | +- South African English in documentation (organisation, colour, centre) |
| 74 | + |
| 75 | +## Test Organisation |
| 76 | + |
| 77 | +Tests live in `tests/Unit/` using Pest v4 syntax (`test('...', fn() => expect(...)->toBe(...))`). |
| 78 | + |
| 79 | +Tests are split by method and concern: `NameFixTest`, `NameFixEdgeCasesTest`, `NameFixNegativeFlowTest`, `NameFixSpecialCharactersTest`, etc. Bug regressions get dedicated test files (e.g., `ArrayCombineValidationBugFixTest`, `UppercaseAccentMappingBugFixTest`). |
| 80 | + |
| 81 | +Mutation testing target MSI: 88%. |
| 82 | + |
| 83 | +## CI |
| 84 | + |
| 85 | +GitHub Actions runs the test matrix against PHP 8.3, 8.4, and 8.5 with vulnerability scanning (osv-scanner + Enlightn). |
0 commit comments