Skip to content

Develop#9

Merged
walmir-silva merged 19 commits intomainfrom
develop
Mar 4, 2026
Merged

Develop#9
walmir-silva merged 19 commits intomainfrom
develop

Conversation

@walmir-silva
Copy link
Contributor

No description provided.

- SanitizerEngine with idempotent sanitize pipeline
- AttributeSanitizer: #[Sanitize] attribute-driven field sanitization
- SanitizationContextImpl: immutable fluent builder (readonly)
- 33 built-in rules across String, Html, Numeric, Type, Date, Filter, Brazilian
- SanitizerConfiguration with trackSanitizations, allowNullOverwrite
- Integration: ProcessorBridge for reactive pipeline compatibility
- 86 tests: AttributeSanitizer, SanitizerEngine, all 33 rule classes
- Conformance: ImmutableStateTest, ArchitecturalContractTest
- PHPUnit 12 compatible attribute-based annotations
- SanitizerServiceProvider: replace 'use ...\String' with 12 individual
  class imports (String is a reserved PHP class name)
- HtmlRulesTest: fix testStripTagsWithAllowed expected value
  PHP strip_tags() preserves text nodes inside stripped tags:
  '<b>hello</b><script>x</script>' with allowed='<b>' → '<b>hello</b>x'
- Apply psalm --alter #[Override] on all interface implementations
- Rename QualityDirectiveV40Test → ArchitecturalContractTest

All changes verified: kcode test passes (86 tests, no failures)
- Adds kariricode/property-inspector v2.0.0 from Packagist to require block
- Provides PropertyInspector, AttributeAnalyzer, and PropertyAccessor
- Enables reflection metadata caching per class (no re-inspection on repeated calls)
- Replaces zero-dependency design with a single dependency on the framework's
  canonical attribute-inspection library
- New SanitizeAttributeHandler: implements PropertyAttributeHandler +
  PropertyChangeApplier; collects #[Sanitize] rules per property
- AttributeSanitizer: replaces raw ReflectionClass loop with
  PropertyInspector::inspect() + SanitizeAttributeHandler
- PropertyAccessor used for writing sanitized values back to objects
- Gains reflection metadata cache from AttributeAnalyzer

kcode test: 86 tests, 0 failures
…isting test classes

Refactor all 8 pre-existing test files to comply with ARFA 1.43 V4.0
and PHPUnit 12+ standards:
- Add #[Test] attribute to every test method
- Add #[CoversClass] (or #[CoversNothing] for conformance/integration tests)
- Split omnibus testGetName() into individual granular test methods
- Use assertSame with literal string constants for rule name assertions
- Ensure declare(strict_types=1) in all test files

Affects: AttributeSanitizerTest, SanitizerServiceProviderTest,
InMemoryRuleRegistryTest, SanitizationContextImplTest, SanitizerEngineTest,
ArchitecturalContractTest, ImmutableStateTest, FullRuleRegistrationTest
Refactor 7 rule test files to comply with PHPUnit 12 and ARFA standards:
- Add #[Test] attribute to every test method
- Add #[CoversClass] for each rule class under test
- Split testGetName() into individual testXxxRuleName() methods
  (one assertSame per method, using literal string constants)
- declare(strict_types=1) verified in all files

Covers: BrazilianRulesTest, DateRulesTest, FilterRulesTest, HtmlRulesTest,
NumericRulesTest, StringRulesTest, TypeRulesTest
…rt types

Create 5 new test files covering previously untested production classes:
- SanitizationResultTest: FieldModification, SanitizationResult (merge, count, get)
- SanitizeAttributeHandlerTest: handleAttribute, merge, non-Sanitize passthrough,
  setProcessedValues, applyChanges, ReflectionException-catch branch (7 methods)
- SanitizationEventsTest: SanitizationStartedEvent, SanitizationCompletedEvent
  with all constructor paths including default timestamps
- SanitizationExceptionsTest: InvalidRuleException + SanitizationException
  factory methods with and without previous Throwable
- ProcessorBridgeTest: process() with sanitized output and empty-data path

Brings class coverage from 87.50% to 100% (48/48 classes)
…arameter() pattern

Replace (string)/(int)/(bool) casts on mixed getParameter() return values
with explicit is_string/is_int/is_bool narrowing to satisfy PHPStan level 9.

Pattern applied consistently across all 11 String rules:
  Before: $max = (int) $context->getParameter('max', 255);
  After:  $maxRaw = $context->getParameter('max', 255);
          $max = is_int($maxRaw) ? $maxRaw : 255;

Specific rules fixed:
  - TrimRule: characters parameter
  - PadRule: length (int), pad (string), side (string)
  - RegexReplaceRule: pattern (string), replacement (string)
  - ReplaceRule: search/replace — simplified to is_string guard with early return
  - SlugRule: separator parameter
  - TruncateRule: max (int), suffix (string)
  - CapitalizeRule, LowerCaseRule, UpperCaseRule, NormalizeWhitespaceRule,
    NormalizeLineEndingsRule, StripNonPrintableRule: cs-fixer style fixes only

Resolves PHPStan cast.string and cast.int errors in String rule namespace
…ameter() pattern

Apply the same type-narrowing idiom to all 5 Html rules to eliminate
PHPStan missingType.cast.string / cast.int errors at level 9:

- HtmlDecodeRule: flags (int), encoding (string)
- HtmlEncodeRule: flags (int), encoding (string), double_encode (bool)
- HtmlPurifyRule: allowed (string)
- StripTagsRule: allowed (string)
- UrlEncodeRule: raw (bool)

Uses explicit is_int / is_string / is_bool narrowing before using
the parameter value, with typed defaults as fallback
…, Date, Filter, Type and Brazilian rules

Numeric:
  - RoundRule: extract 10**precision into $multiplier, cast to (float)
    to resolve Psalm InvalidOperand in strict binary operands mode
  - ClampRule, ToIntRule, ToFloatRule: cs-fixer Yoda-style comparisons

Date:
  - NormalizeDateRule: from/to narrowed from mixed to string
  - TimestampToDateRule: format/timezone narrowed from mixed to string;
    timezone additionally validated as non-empty-string to satisfy
    Psalm ArgumentTypeCoercion for DateTimeZone::__construct

Filter:
  - EmailFilterRule: add @psalm-suppress RedundantCast to resolve
    PHPStan/Psalm disagreement on filter_var FILTER_SANITIZE_EMAIL
  - AlphaOnlyRule, AlphanumericOnlyRule, DigitsOnlyRule: cs-fixer style

Type / Brazilian:
  - ToBoolRule, ToStringRule, ToArrayRule: cs-fixer style
  - FormatCepRule, FormatCnpjRule, FormatCpfRule: Yoda comparisons
…salm errors

SanitizeAttributeHandler:
  - Typed $fieldRules property from list<mixed> to the full union matching
    SanitizerEngine::sanitize() signature to fix AttributeSanitizer argument.type
  - Updated getFieldRules() return type PHPDoc accordingly

SanitizerEngine:
  - Added @param array<string, mixed> to resolveValue() private method
  - Added @param union type annotation to resolveRule() parameter $definition
  - Added @return array{0: SanitizationRule, 1: array<string, mixed>} to resolveRule

Sanitize (Attribute):
  - Added @param PHPDoc to variadic __construct parameter
  - Added intermediate @var typed local to satisfy assign.propertyType
    (PHPStan cannot infer list<string|array{...}> from variadic spread)

AttributeSanitizer:
  - Resolved argument.type mismatch via improved SanitizeAttributeHandler types

ProcessorBridge:
  - Added SanitizationRule import
  - Added full typed union @param/@var annotations matching engine signature
  - Resolves missingType.iterableValue and argument.type errors
Apply PHP CS Fixer Yoda-style comparison rule across all support
infrastructure classes that were not touched by previous type-safety commits:

  Before: $x === null  →  After: null === $x
  Before: $x !== ''   →  After: '' !== $x

Files: RuleRegistry, SanitizationContext, SanitizationRule contracts,
       SanitizerConfiguration, SanitizationCompletedEvent, SanitizationStartedEvent,
       InvalidRuleException, SanitizationException, FieldModification,
       SanitizationResult, InMemoryRuleRegistry, SanitizationContextImpl,
       SanitizerServiceProvider

No logic changes — pure cs-fixer style conformance
- Remove root-level .php-cs-fixer.php (config now lives at .kcode/php-cs-fixer.php,
  managed by kariricode/devkit)
- Update README.md to reflect current public API, coverage badge,
  and ARFA 1.43 V4.0 compliance status

No functional changes to production code or tests
Document key design decisions for the sanitizer:
- ADR-001: Rule Registry Pattern — alias-based InMemoryRuleRegistry
- ADR-002: Property Inspector Integration — kariricode/property-inspector
  replaces raw Reflection API for attribute scanning
- ADR-003: Sanitization Context Immutability — final readonly SanitizationContextImpl
- ADR-004: ARFA 1.43 Rule Passthrough Contract — non-matching types returned unchanged
- ADR-005: Zero-Dependency Rule Implementation — all 33 rules use PHP built-ins only

Also adds docs/README.md index linking all ADRs and SPECs.
Library projects have no runtime environment requirements.
.env is already gitignored; .env.example is misleading and unnecessary.
@walmir-silva walmir-silva merged commit 9b85487 into main Mar 4, 2026
8 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant