Skip to content

Commit ec59b66

Browse files
committed
Create a repository for Respect\Masker
I'm planning on creating a validation in Validation named "Masked". I created this as a standalone library since masking functionality doesn't seem to belong in Validation. Apart from that, having this as a standalone project allows people to use it for other use cases beyond what Validation needs.
0 parents  commit ec59b66

File tree

10 files changed

+3330
-0
lines changed

10 files changed

+3330
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: Continuous Integration
2+
3+
on:
4+
push: ~
5+
pull_request: ~
6+
7+
jobs:
8+
tests:
9+
name: Tests
10+
11+
runs-on: ubuntu-latest
12+
13+
strategy:
14+
matrix:
15+
php-version:
16+
- "8.5"
17+
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v6
21+
22+
- name: Install PHP
23+
uses: shivammathur/setup-php@v2
24+
with:
25+
php-version: ${{ matrix.php-version }}
26+
coverage: none
27+
28+
- name: Install Dependencies
29+
run: composer install --prefer-dist ${{ matrix.composer-extra-arguments }}
30+
31+
- name: Run Unit Tests
32+
run: ./vendor/bin/phpunit
33+
34+
code-coverage:
35+
name: Code coverage
36+
37+
runs-on: ubuntu-latest
38+
39+
steps:
40+
- name: Checkout
41+
uses: actions/checkout@v6
42+
43+
- name: Install PHP
44+
uses: shivammathur/setup-php@v2
45+
with:
46+
php-version: 8.5
47+
coverage: pcov
48+
49+
- name: Install Dependencies
50+
run: composer install --prefer-dist ${{ matrix.composer-extra-arguments }}
51+
52+
- name: Generating Code Coverage Report
53+
run: ./vendor/bin/phpunit --coverage-clover=coverage.xml
54+
55+
- name: Send Code Coverage Report to Codecov.io
56+
uses: codecov/codecov-action@v5
57+
with:
58+
token: ${{ secrets.CODECOV_TOKEN }}
59+
60+
static-analysis:
61+
name: Static Analysis
62+
63+
runs-on: ubuntu-latest
64+
65+
steps:
66+
- name: Checkout
67+
uses: actions/checkout@v6
68+
69+
- name: Install PHP
70+
uses: shivammathur/setup-php@v2
71+
with:
72+
php-version: 8.5
73+
coverage: none
74+
75+
- name: Install dependencies
76+
run: composer install --prefer-dist
77+
78+
- name: Run PHP_CodeSniffer
79+
run: vendor/bin/phpcs
80+
81+
- name: Run PHPStan
82+
run: vendor/bin/phpstan analyze

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.phpcs.cache
2+
.phpunit.cache/
3+
/vendor/

README.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Respect\Masker
2+
3+
[![Build Status](https://img.shields.io/github/actions/workflow/status/Respect/Masker/continuous-integration.yml?branch=master&style=flat-square)](https://github.com/Respect/Masker/actions/workflows/continuous-integration.yml)
4+
[![Code Coverage](https://img.shields.io/codecov/c/github/Respect/Masker?style=flat-square)](https://codecov.io/gh/Respect/Masker)
5+
[![Latest Stable Version](https://img.shields.io/packagist/v/respect/masker.svg?style=flat-square)](https://packagist.org/packages/respect/masker)
6+
[![Total Downloads](https://img.shields.io/packagist/dt/respect/masker.svg?style=flat-square)](https://packagist.org/packages/respect/masker)
7+
[![License](https://img.shields.io/packagist/l/respect/masker.svg?style=flat-square)](https://packagist.org/packages/respect/masker)
8+
9+
A powerful and flexible PHP library for masking sensitive text data using intuitive range-based patterns.
10+
11+
Whether you need to hide credit card numbers, mask email addresses, or protect user privacy, Masker gives you precise control over what gets hidden and what stays visible.
12+
13+
## Installation
14+
15+
```bash
16+
composer require respect/masker
17+
```
18+
19+
## Usage
20+
21+
### Basic Usage
22+
23+
```php
24+
use Respect\Masker\TextMasker;
25+
26+
$masker = new TextMasker();
27+
28+
echo $masker->mask('1234123412341234', '1-3,8-12');
29+
// Outputs: ***4123*****1234
30+
```
31+
32+
## API
33+
34+
### `mask`
35+
36+
- `mask(string $input, string $range): string`
37+
- `mask(string $input, string $range, string $replacement): string`
38+
39+
Masks the input string according to the specified range.
40+
41+
**Parameters:**
42+
43+
- `$input`: The string to mask
44+
- `$range`: Comma-separated range specifications
45+
- `$replacement`: The character to use for masking (default `*`)
46+
47+
**Returns:** The masked string
48+
49+
**Throws:** `InvalidArgumentException` when invalid ranges are provided
50+
51+
### `isValidRange`
52+
53+
- `isValidRange(string $range): bool`
54+
55+
Validates whether the mask range specification is syntactically correct.
56+
57+
## Range Syntax
58+
59+
| Pattern | Description | Example |
60+
| ------- | ------------------------------- | --------------------- |
61+
| `N` | Single position (1-based) | `3` |
62+
| `N-` | From position N to end | `1-` |
63+
| `N-M` | Range from position N to M | `1-3` |
64+
| `-N` | Last N characters | `-3` |
65+
| `C-M` | From character C to character M | `1-@` |
66+
| `\N` | Escaped numeral character | `\5` |
67+
| `\C` | Escaped special character | `\-`, `\,`, or `\\\\` |
68+
69+
Multiple ranges can be specified using commas: `1-B,6-8,10`
70+
71+
### Numeric Positions (1-based)
72+
73+
Use numeric positions to mask specific characters (1-based indexing).
74+
75+
| Range | Input | Output |
76+
| ------ | -------------- | -------------- |
77+
| `1-3` | `password123` | `***ord123` |
78+
| `1-3` | `'12345'` | `***45` |
79+
| `7-12` | `'1234567890'` | `123456******` |
80+
81+
#### Character Delimiters
82+
83+
Use character delimiters to mark ranges between characters in the string.
84+
85+
| Range | Input | Output |
86+
| ------ | --------------------- | --------------------- |
87+
| `1-@` | `username@domain.com` | `********@domain.com` |
88+
| `A-\5` | `ABCDD1234567890EFGH` | `*********567890EFGH` |
89+
| `A-\-` | `ABCD-1234567890EFGH` | `####-1234567890EFGH` |
90+
| `B-\,` | `ABC,DEF,GHI` | `**C,DEF,GHI` |
91+
92+
#### Multiple Ranges
93+
94+
Combine multiple ranges using commas to mask non-contiguous sections.
95+
96+
| Range | Input | Output |
97+
| ------------ | -------------------- | --------------------- |
98+
| `1-3,8-12` | `1234123412341234` | `***4123*****1234` |
99+
| `1,3,5` | `'12345'` | `*2*4*` |
100+
| `1-3,6-8,10` | `abcdefghij` | `***de***j` |
101+
| `1,3,5` | `12345` | `*2*4*` |
102+
| `1-3,8-12` | `'123456789012'` | `***45678******` |
103+
| `A-D,5-8` | `ABCD1234567890EFGH` | `####D####567890EFGH` |
104+
| `1-c,2-5` | `abc123def456` | `#####3def456` |
105+
106+
#### Special Patterns
107+
108+
**Mask to end**: Use `1-` to mask from the beginning to the end
109+
**Mask last N**: Use `-N` to mask the last N characters
110+
111+
| Range | Input | Output |
112+
| ----- | ---------- | ---------- |
113+
| `1-` | `12345678` | `********` |
114+
| `-2` | `123456` | `1234**` |
115+
| `-3` | `abcdefgh` | `abcde***` |
116+
117+
#### Escaping Special Characters
118+
119+
Escape special characters with backslash when they need to be used as literals.
120+
121+
| Range | Input | Output |
122+
| -------- | ---------------------------- | ---------------------------- |
123+
| `3-\5` | `1234567890` | `12**567890` |
124+
| `1-\-` | `email-something@domain.com` | `*****-something@domain.com` |
125+
| `1-\\\\` | `path\to\file` | `****\to\file` |
126+
127+
To use `-`, `\` and `,` as delimiters, you must always add backslashes before them.
128+
129+
#### Unicode Support
130+
131+
Full support for UTF-8 strings including accented characters.
132+
133+
| Range | Input | Output |
134+
| ------- | ---------------- | ---------------- |
135+
| `1-` | `oftalmoscópico` | `**************` |
136+
| `2-6,9` | `áéíóúãõçüñ` | `á*****õç*ñ` |
137+
| `-4` | `españolñç` | `españolñ*` |
138+
139+
## License
140+
141+
This project is licensed under the ISC License - see the LICENSE file for details.

composer.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"name": "respect/masker",
3+
"type": "library",
4+
"description": "Mask sensitive text data using flexible range-based patterns",
5+
"require": {
6+
"symfony/polyfill-mbstring": "^1.33",
7+
"php": "^8.5"
8+
},
9+
"require-dev": {
10+
"phpunit/phpunit": "^12.5",
11+
"phpstan/phpstan": "^2.1",
12+
"phpstan/extension-installer": "^1.4",
13+
"phpstan/phpstan-deprecation-rules": "^2.0",
14+
"phpstan/phpstan-phpunit": "^2.0",
15+
"respect/coding-standard": "^5.0"
16+
},
17+
"license": "ISC",
18+
"autoload": {
19+
"psr-4": {
20+
"Respect\\Masker\\": "src/"
21+
}
22+
},
23+
"autoload-dev": {
24+
"psr-4": {
25+
"Respect\\Masker\\Test\\": "tests/"
26+
}
27+
},
28+
"authors": [
29+
{
30+
"name": "Henrique Moody",
31+
"email": "henriquemoody@gmail.com"
32+
}
33+
],
34+
"scripts": {
35+
"lint": "phpcs",
36+
"test": "phpunit",
37+
"analyze": "phpstan"
38+
},
39+
"config": {
40+
"allow-plugins": {
41+
"phpstan/extension-installer": true,
42+
"dealerdirect/phpcodesniffer-composer-installer": true
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)