Skip to content

Commit 885ca2d

Browse files
authored
Merge pull request #2 from MaestroError/wrapper-for-builder-pattern
Wrapper created and some bug fixes
2 parents 83c48f2 + 5bfbc09 commit 885ca2d

File tree

8 files changed

+308
-19
lines changed

8 files changed

+308
-19
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ on:
77
# branches: [main]
88

99
jobs:
10-
build:
10+
test:
1111
runs-on: ubuntu-latest
1212
steps:
13-
- uses: actions/checkout@v2
14-
- name: Set up PHP
15-
uses: shivammathur/setup-php@v2
16-
with:
17-
php-version: '8.2'
18-
- name: Install dependencies
19-
run: composer install --prefer-dist --no-progress
13+
- uses: actions/checkout@v2
14+
- name: Set up PHP
15+
uses: shivammathur/setup-php@v2
16+
with:
17+
php-version: "8.2"
18+
- name: Install dependencies
19+
run: composer install --prefer-dist --no-progress
2020

2121
- name: Run tests
2222
run: ./vendor/bin/pest

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ Examples: `->exact("hello world", false, "1+")`
4848

4949
- Add facade for Laravel
5050
- Wrap Builder in class for static start
51-
- "string" and "source" for builder start
52-
- "start" and "pattern" for builderPattern start
51+
- "string" and "source" for builder start✔️
52+
- "start" and "pattern" for builderPattern start✔️
5353
- Write documentation (add credit for https://regexr.com/ and ChatGPT)
54-
- Add automated tests on PR creation or on marging to main branch
54+
- Add automated tests on PR creation or on marging to main branch ✔️
5555

5656
##### Coming next
5757

src/Builder.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
use Maestroerror\EloquentRegex\Contracts\BuilderContract;
77
use Maestroerror\EloquentRegex\OptionsManager;
88
use Maestroerror\EloquentRegex\OptionsBuilder;
9-
use Maestroerror\EloquentRegex\Traits\BuilderPatternTraits\BuilderPatternMethods;
9+
use Maestroerror\EloquentRegex\Traits\BuilderTraits\BuilderPatternMethods;
10+
use Maestroerror\EloquentRegex\Traits\BuilderTraits\InitMethods;
1011
use Maestroerror\EloquentRegex\Patterns\TextOrNumbersPattern;
1112
use Maestroerror\EloquentRegex\Patterns\EmailPattern;
1213
use Maestroerror\EloquentRegex\Patterns\UrlPattern;
@@ -26,7 +27,7 @@
2627

2728
class Builder implements BuilderContract {
2829

29-
use BuilderPatternMethods;
30+
use BuilderPatternMethods, InitMethods;
3031

3132
/**
3233
* The string to be processed with regex.

src/EloquentRegex.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Maestroerror\EloquentRegex;
4+
5+
use Maestroerror\EloquentRegex\Builder;
6+
7+
8+
class EloquentRegex {
9+
10+
public static function string(string $str) {
11+
return (new Builder)->source($str);
12+
}
13+
14+
public static function source(string $str) {
15+
return (new Builder)->source($str);
16+
}
17+
18+
public static function start(string $str) {
19+
return (new Builder)->source($str)->start();
20+
}
21+
22+
public static function customPattern(string $str) {
23+
return (new Builder)->source($str)->start();
24+
}
25+
26+
public static function builder() {
27+
return new Builder;
28+
}
29+
}

src/Traits/BuilderPatternTraits/BuilderPatternMethods.php renamed to src/Traits/BuilderTraits/BuilderPatternMethods.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Maestroerror\EloquentRegex\Traits\BuilderPatternTraits;
3+
namespace Maestroerror\EloquentRegex\Traits\BuilderTraits;
44

55
use Maestroerror\EloquentRegex\Patterns\BuilderPattern;
66
use Maestroerror\EloquentRegex\Contracts\BuilderContract;
@@ -38,15 +38,15 @@ public function start(): BuilderPattern {
3838
* @param callable|null $callback A callback function that receives a BuilderPattern instance to define the regex pattern.
3939
* @return BuilderContract|BuilderPattern Returns the main Builder instance after the pattern is defined.
4040
*/
41-
public function pattern(callable|null $callback): BuilderContract|BuilderPattern {
41+
public function pattern(callable|null $callback = null): BuilderContract|BuilderPattern {
4242
if (is_null($callback)) {
4343
return $this->start();
4444
}
4545
// Pass the current Builder instance to the BuilderPattern
4646
$this->pattern = new BuilderPattern($this);
4747
// Run callback to create pattern
48-
$builderPattern = $callback($this->pattern);
48+
$callback($this->pattern);
4949
// return back the Builder object
50-
return $builderPattern->end();
50+
return $this->pattern->end();
5151
}
5252
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Maestroerror\EloquentRegex\Traits\BuilderTraits;
4+
5+
use Maestroerror\EloquentRegex\Patterns\BuilderPattern;
6+
use Maestroerror\EloquentRegex\Contracts\BuilderContract;
7+
8+
/**
9+
* trait BuilderPatternMethods
10+
*
11+
* Used in Maestroerror\EloquentRegex\Builder class to enhance it with starting methods
12+
*/
13+
trait InitMethods {
14+
15+
public function source(string $str): self {
16+
$this->setString($str);
17+
return $this;
18+
}
19+
}
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
<?php
2+
3+
use Maestroerror\EloquentRegex\EloquentRegex;
4+
5+
// Custom Pattern tests:
6+
7+
it('reproduces alt prefix pattern from HSA using facade', function () {
8+
$regex = EloquentRegex::builder()->start()
9+
->exact("alt=")
10+
->group(function ($pattern) {
11+
$pattern->doubleQuote()->orPattern(function ($pattern) {
12+
$pattern->singleQuote();
13+
});
14+
})->toRegex();
15+
16+
expect($regex)->toBe("alt\=(\"|')");
17+
});
18+
19+
it('reproduces hashtag prefix pattern from HSA using facade', function () {
20+
$regex = EloquentRegex::builder()->start()
21+
->lookBehind(function ($pattern) {
22+
$pattern->charSet(function ($pattern) {
23+
$pattern->doubleQuote()->closeAngleBracket()->addRawRegex("\\s");
24+
});
25+
})->hash()->toRegex();
26+
27+
expect($regex)->toBe('(?<=["\>\s])\#');
28+
});
29+
30+
it('reproduces Text suffix pattern from HSA using facade', function () {
31+
$regex = EloquentRegex::builder()->start()
32+
->openAngleBracket()->slash()->alphanumericRange(0, 10)->closeAngleBracket()
33+
->toRegex();
34+
35+
expect($regex)->toBe('\<\/[a-zA-Z0-9]{0,10}\>');
36+
});
37+
38+
it('constructs regex for simple email validation using facade', function () {
39+
$regex = EloquentRegex::builder()->start()
40+
->textLowercase()
41+
->atSymbol()
42+
->textLowercase()
43+
->dot()
44+
->textLowercaseRange(2, 4)
45+
->toRegex();
46+
47+
expect($regex)->toBe('[a-z]+@[a-z]+\.[a-z]{2,4}');
48+
});
49+
50+
it('constructs regex for URL validation using facade', function () {
51+
$regex = EloquentRegex::builder()->pattern()
52+
->exact(['http', 'https'])
53+
->colon()
54+
->doubleSlash()
55+
->text()
56+
->dot()
57+
->text()
58+
->toRegex();
59+
60+
expect($regex)->toBe('(http|https)\:\/\/[a-zA-Z]+\.[a-zA-Z]+');
61+
});
62+
63+
it('constructs regex for specific phone number format using facade', function () {
64+
$regex = EloquentRegex::builder()->pattern(function ($p) {
65+
$p->openParenthesis()->digits(3)->closeParenthesis()
66+
->space()
67+
->digits(3)->dash()->digits(4);
68+
})->toRegex();
69+
70+
expect($regex)->toBe('\(\d{3}\) \d{3}\-\d{4}');
71+
});
72+
73+
it('extracts dates in specific format from text using facade', function () {
74+
$matches = EloquentRegex::customPattern("Meeting on 2021-09-15 and 2021-10-20")
75+
->digits(4)
76+
->dash()
77+
->digits(2)
78+
->dash()
79+
->digits(2)
80+
->get();
81+
82+
expect($matches)->toEqual(['2021-09-15', '2021-10-20']);
83+
});
84+
85+
it('validates usernames in a string using facade', function () {
86+
$check = EloquentRegex::customPattern("Users: user_123, JohnDoe99")
87+
->alphanumeric()
88+
->underscore("?")
89+
->digitsRange(0, 2)
90+
->checkString();
91+
92+
expect($check)->toBeTrue();
93+
});
94+
95+
it('extracts hashtags from text using facade', function () {
96+
$matches = EloquentRegex::start("#hello #world This is a #test")
97+
->hash()
98+
->text()
99+
->get();
100+
101+
expect($matches)->toEqual(['#hello', '#world', '#test']);
102+
});
103+
104+
it('extracts secret coded messages from text using facade', function () {
105+
$text = "Normal text {secret: message one} more text {secret: another hidden text} end";
106+
$matches = EloquentRegex::start($text)
107+
->lookBehind(function ($pattern) {
108+
$pattern->openCurlyBrace()->exact('secret: ');
109+
})
110+
->lazy()->anyChar()
111+
->lookAhead(function ($pattern) {
112+
$pattern->closeCurlyBrace();
113+
})
114+
->get();
115+
116+
expect($matches)->toEqual(['message one', 'another hidden text']);
117+
});
118+
119+
// Ready-to-use pattern tests:
120+
121+
// TextOrNumbersPattern
122+
it('validates text with numbers correctly', function () {
123+
$builder = EloquentRegex::source("Text123");
124+
125+
$check = $builder->textOrNumbers()->check();
126+
127+
expect($check)->toBeTrue();
128+
});
129+
130+
// EmailPattern
131+
it('validates an email address correctly', function () {
132+
$builder = EloquentRegex::source("[email protected]");
133+
134+
$check = $builder->email()->check();
135+
136+
expect($check)->toBeTrue();
137+
});
138+
139+
// DomainNamePattern
140+
it('validates a domain name correctly', function () {
141+
$builder = EloquentRegex::string("example.com");
142+
143+
$check = $builder->domainName()->check();
144+
145+
expect($check)->toBeTrue();
146+
});
147+
148+
// DatePattern
149+
it('validates a date format correctly', function () {
150+
$builder = EloquentRegex::string("2023-01-01");
151+
152+
$check = $builder->date('Y-m-d')->check();
153+
154+
expect($check)->toBeTrue();
155+
});
156+
157+
// TimePattern
158+
it('validates a time format correctly', function () {
159+
$builder = EloquentRegex::string("23:59");
160+
161+
$check = $builder->time('H:i')->check();
162+
163+
expect($check)->toBeTrue();
164+
});
165+
166+
// IPAddressPattern
167+
it('validates an IPv4 address correctly', function () {
168+
$builder = EloquentRegex::string("192.168.1.1");
169+
170+
$check = $builder->ipAddress()->check();
171+
172+
expect($check)->toBeTrue();
173+
});
174+
175+
// IPv6AddressPattern
176+
it('validates an IPv6 address correctly', function () {
177+
$builder = EloquentRegex::string("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
178+
179+
$check = $builder->ipv6Address()->check();
180+
181+
expect($check)->toBeTrue();
182+
});
183+
184+
// CreditCardNumberPattern
185+
it('validates a credit card number correctly', function () {
186+
$builder = EloquentRegex::source("4111111111111111"); // A common Visa test number
187+
188+
$check = $builder->creditCardNumber()->check();
189+
190+
expect($check)->toBeTrue();
191+
});
192+
193+
// PhonePattern
194+
it('validates a phone number correctly', function () {
195+
$builder = EloquentRegex::string("+1 (123) 456-7890");
196+
197+
$check = $builder->phone()->check();
198+
199+
expect($check)->toBeTrue();
200+
});
201+
202+
// UsernamePattern
203+
it('validates a username correctly', function () {
204+
$builder = EloquentRegex::string("user_123");
205+
206+
$check = $builder->username()->check();
207+
208+
expect($check)->toBeTrue();
209+
});
210+
211+
// HtmlTagPattern
212+
it('identifies HTML content correctly', function () {
213+
$builder = EloquentRegex::source("<div>example</div>");
214+
215+
$check = $builder->htmlTag()->check();
216+
217+
expect($check)->toBeTrue();
218+
});
219+
220+
// CurrencyPattern
221+
it('validates currency format correctly', function () {
222+
$builder = EloquentRegex::string("$100.00");
223+
224+
$check = $builder->currency()->check();
225+
226+
expect($check)->toBeTrue();
227+
});
228+
229+
// FilePathPattern
230+
it('validates a Unix file path correctly', function () {
231+
$string = "/user/directory/file.txt";
232+
$builder = EloquentRegex::string($string);
233+
234+
$check = $builder->filePath([
235+
"isDirectory" => false,
236+
"isFile" => "txt",
237+
])->check();
238+
239+
expect($check)->toBeTrue();
240+
});

tests/Feature/Patterns/FilePathWinPatternTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
$check = $builder->filePathWin(0, null, true)->check();
5454

5555
expect($check)->toBeTrue();
56-
});
56+
})->onlyOnWindows();
5757

5858
it('checks file using array options', function () {
5959
$string = __DIR__.'\..\..\TestFiles\document.txt';
@@ -66,4 +66,4 @@
6666
])->check();
6767

6868
expect($check)->toBeTrue();
69-
});
69+
})->onlyOnWindows();

0 commit comments

Comments
 (0)