Skip to content

feat: add hideEmail transformer for PII masking#42

Merged
viniciusvts merged 1 commit intoSSolWEB:mainfrom
mvanhorn:osc/25-add-hide-email-transformer
Apr 22, 2026
Merged

feat: add hideEmail transformer for PII masking#42
viniciusvts merged 1 commit intoSSolWEB:mainfrom
mvanhorn:osc/25-add-hide-email-transformer

Conversation

@mvanhorn
Copy link
Copy Markdown
Contributor

Summary

Adds hideEmail - a new transformer that masks an email address for privacy / compliance logging (LGPD / GDPR), matching the existing Brazilian-format maskBrCpf / maskBrPhone / etc. helpers.

Why this matters

Issue #25 laid out the use case (audit logs, "reset link sent to j***@gm***.com", customer-support dashboards) and the existing workaround - every caller manually explode('@', $email) + substr(), which drifts in style and edge-case handling. One reusable transformer removes that surface.

Changes

  • src/Transformers/HideEmailTransformer.php: new final class implementing StringTransformerInterface.
    • filter_var(..., FILTER_VALIDATE_EMAIL) short-circuits: invalid input returns unchanged (matches how MaskBrCpf returns early when digits don't match).
    • Splits the domain on the first dot so compound suffixes survive (contoso.co.uk -> co*****.co.uk, not the .uk-only result strrpos would give).
    • mask() keeps the first two characters and pads the rest with *. Segments of length ≤ 2 keep their prefix plus one * so the mask stays visible for short addresses like [email protected].
  • src/StringMorpher.php and src/Instances/StringMorpherInstance.php: add the @method hideEmail(...) hints alongside the existing mask helpers, so IDE autocomplete and static analysis pick it up.
  • tests/Transformers/HideEmailTransformerTest.php: mirror the MaskBrCpfTransformerTest shape - direct transform() cases, short-segment behaviour, invalid-input passthrough, and the SM::hideEmail facade.

Testing

$ vendor/bin/phpunit tests/Transformers/HideEmailTransformerTest.php
OK (4 tests, 15 assertions)

$ vendor/bin/phpunit
OK (120 tests, 756 assertions)

All existing tests still pass. The new transformer is registered through the library's dynamic __call loader - no changes to StringMorpherInstance::__call were needed.

Examples

use SSolWEB\StringMorpher\StringMorpher as SM;

SM::hideEmail('[email protected]'); // jo********@ex*****.com
SM::hideEmail('[email protected]');    // al***@co*****.co.uk
SM::hideEmail('[email protected]');                 // a*@x*.io
SM::hideEmail('not-an-email');           // not-an-email

Fixes #25

This contribution was developed with AI assistance (Claude Code).

Issue SSolWEB#25 asks for an email-masking helper similar to the existing
Brazilian-format maskers (maskBrCpf / maskBrPhone / etc) so callers
don't have to re-implement the explode-and-substr boilerplate every
time they need to log a user email in a compliance-sensitive context.

Add HideEmailTransformer that:
- Returns the input unchanged when filter_var rejects it as an email
  or when the domain has no dot (nothing to preserve).
- Splits on the first dot in the domain so compound suffixes like
  .co.uk survive intact (contoso.co.uk -> co*****.co.uk).
- Keeps the first two characters of the local part and host, replaces
  the remainder with '*', and preserves the TLD chain.
- Short local / host parts (<=2 chars) keep whatever prefix they
  have plus a single '*' so the mask stays visible for edge cases
  like [email protected] -> a*@x*.io.

Examples:
  [email protected] -> jo********@ex*****.com
  [email protected]    -> al***@co*****.co.uk
  [email protected]                 -> a*@x*.io
  not-an-email           -> not-an-email

Wires the new method through the existing dynamic-transformer
pattern: adds @method hints on StringMorpher and
StringMorpherInstance, and a dedicated HideEmailTransformerTest
covering the happy path, short-segment fallback, invalid input
passthrough, and the SM::hideEmail facade.

Fixes SSolWEB#25
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 22, 2026

👷 Deploy request for string-morpher pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 9a301a2

@viniciusvts
Copy link
Copy Markdown
Member

viniciusvts commented Apr 22, 2026

Thank you for your contribution!

@viniciusvts viniciusvts merged commit 12942d0 into SSolWEB:main Apr 22, 2026
9 of 13 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.

[Feature]: Add hideEmail method for email masking (privacy/LGPD)

2 participants