Skip to content

Commit 48394ba

Browse files
committed
group methods for builder pattern and 200 tests milestone
1 parent 0472a76 commit 48394ba

File tree

4 files changed

+159
-10
lines changed

4 files changed

+159
-10
lines changed

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ Examples: `->dot("zeroOrMore")` `->exact("hello worls", false, "1+")`
4949

5050
- Extend BuilderPattern, try to add methods:
5151

52-
- group(callable $callback): Creates a grouped subpattern.
53-
- nonCapturingGroup(callable $callback): Creates a non-capturing group.
54-
- orPattern(): Alternation, allowing for multiple possibilities.
55-
- lookAhead(callable $callback): Positive lookahead assertion.
56-
- lookBehind(callable $callback): Positive lookbehind assertion.
57-
- negativeLookAhead(callable $callback): Negative lookahead assertion.
58-
- negativeLookBehind(callable $callback): Negative lookbehind assertion.
59-
- Raw regex methods for advanced users.
52+
- group(callable $callback): Creates a grouped subpattern.✔️
53+
- nonCapturingGroup(callable $callback): Creates a non-capturing group.✔️
54+
- orPattern(): Alternation, allowing for multiple possibilities.✔️
55+
- lookAhead(callable $callback): Positive lookahead assertion.✔️
56+
- lookBehind(callable $callback): Positive lookbehind assertion.✔️
57+
- negativeLookAhead(callable $callback): Negative lookahead assertion.✔️
58+
- negativeLookBehind(callable $callback): Negative lookbehind assertion.✔️
59+
- Raw regex methods for advanced users.✔️
6060
- BuilderPattern should be able to reproduce patterns used in HSA
6161

6262
- Add benchmarks and tests for search against large data ✔️

src/Patterns/BuilderPattern.php

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,73 @@ private function getLengthOption($length = null, $minLength = 0, $maxLength = 0)
6565
}
6666

6767
public function group(callable $callback): self {
68-
$subPattern = new self($this->builder);
68+
$subPattern = new self();
6969
$callback($subPattern);
7070
$this->pattern .= '(' . $subPattern->getPattern() . ')';
7171
return $this;
7272
}
7373

7474
public function nonCapturingGroup(callable $callback): self {
75-
$subPattern = new self($this->builder);
75+
$subPattern = new self();
7676
$callback($subPattern);
7777
$this->pattern .= '(?:' . $subPattern->getPattern() . ')';
7878
return $this;
7979
}
8080

81+
public function orPattern(callable $callback): self {
82+
$builder = new self();
83+
$callback($builder);
84+
$this->pattern .= '|' . $builder->getPattern();
85+
return $this;
86+
}
87+
88+
public function lookAhead(callable $callback): self {
89+
$builder = new self();
90+
$callback($builder);
91+
$this->pattern .= '(?=' . $builder->getPattern() . ')';
92+
return $this;
93+
}
94+
95+
public function lookBehind(callable $callback): self {
96+
$builder = new self();
97+
$callback($builder);
98+
$this->pattern .= '(?<=' . $builder->getPattern() . ')';
99+
return $this;
100+
}
101+
102+
public function negativeLookAhead(callable $callback): self {
103+
$builder = new self();
104+
$callback($builder);
105+
$this->pattern .= '(?!' . $builder->pattern . ')';
106+
return $this;
107+
}
108+
109+
public function negativeLookBehind(callable $callback): self {
110+
$builder = new self();
111+
$callback($builder);
112+
$this->pattern .= '(?<!' . $builder->pattern . ')';
113+
return $this;
114+
}
115+
116+
/**
117+
* Adds a raw regex string to the pattern.
118+
*
119+
* @param string $regex The raw regex string to add.
120+
* @return self
121+
*/
122+
public function addRawRegex(string $regex): self {
123+
$this->pattern .= $regex;
124+
return $this;
125+
}
126+
127+
/**
128+
* Wraps a given regex string in a non-capturing group and adds it to the pattern.
129+
*
130+
* @param string $regex The regex string to wrap and add.
131+
* @return self
132+
*/
133+
public function addRawNonCapturingGroup(string $regex): self {
134+
$this->pattern .= '(?:' . $regex . ')';
135+
return $this;
136+
}
81137
}

tests/Feature/BuilderTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
3+
use Maestroerror\EloquentRegex\Builder;
4+

tests/Unit/Patterns/BuilderPatternTest.php

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,3 +441,92 @@
441441
preg_match($regex, 'abcdef', $matches);
442442
expect(isset($matches[1]))->toBeFalse(); // No captured content
443443
});
444+
445+
test('orPattern method combines patterns with alternation correctly', function () {
446+
$builder = new BuilderPattern();
447+
$builder->exact('apple')->orPattern(function($pattern) {
448+
$pattern->exact('orange');
449+
});
450+
451+
$regex = $builder->getInputValidationPattern();
452+
expect(preg_match($regex, 'apple'))->toBe(1);
453+
expect(preg_match($regex, 'orange'))->toBe(1);
454+
expect(preg_match($regex, 'banana'))->toBe(0); // Not part of the alternation
455+
});
456+
457+
test('orPattern can be used multiple times for complex alternation', function () {
458+
$builder = new BuilderPattern();
459+
$builder->exact('apple')->orPattern(function($pattern) {
460+
$pattern->exact('orange');
461+
})->orPattern(function($pattern) {
462+
$pattern->exact('banana');
463+
});
464+
465+
$regex = $builder->getInputValidationPattern();
466+
expect(preg_match($regex, 'apple'))->toBe(1);
467+
expect(preg_match($regex, 'orange'))->toBe(1);
468+
expect(preg_match($regex, 'banana'))->toBe(1);
469+
expect(preg_match($regex, 'pear'))->toBe(0); // Not part of the alternation
470+
});
471+
472+
test('lookAhead method adds positive lookahead correctly', function () {
473+
$builder = new BuilderPattern();
474+
$builder->digits()->lookAhead(function($pattern) {
475+
$pattern->character('D');
476+
});
477+
478+
$regex = $builder->getMatchesValidationPattern();
479+
expect(preg_match($regex, '3D'))->toBe(1); // Digit followed by 'D'
480+
expect(preg_match($regex, '3A'))->toBe(0); // Digit not followed by 'D'
481+
});
482+
483+
test('lookBehind method adds positive lookbehind correctly', function () {
484+
$builder = new BuilderPattern();
485+
$builder->lookBehind(function($pattern) {
486+
$pattern->character('P');
487+
})->digits();
488+
489+
$regex = $builder->getMatchesValidationPattern();
490+
expect(preg_match($regex, 'P3'))->toBe(1); // Digit preceded by 'P', in case of get() ot will return only digit
491+
expect(preg_match($regex, 'A3'))->toBe(0); // Digit not preceded by 'P'
492+
});
493+
494+
test('negativeLookAhead method adds negative lookahead correctly', function () {
495+
$builder = new BuilderPattern();
496+
$builder->digits()->negativeLookAhead(function($pattern) {
497+
$pattern->character('-');
498+
});
499+
500+
$regex = $builder->getMatchesValidationPattern();
501+
expect(preg_match($regex, '3A'))->toBe(1); // Digit not followed by '-'
502+
expect(preg_match($regex, '3-'))->toBe(0); // Digit followed by '-'
503+
});
504+
505+
test('negativeLookBehind method adds negative lookbehind correctly', function () {
506+
$builder = new BuilderPattern();
507+
$builder->negativeLookBehind(function($pattern) {
508+
$pattern->character('-');
509+
})->digits();
510+
511+
$regex = $builder->getMatchesValidationPattern();
512+
expect(preg_match($regex, 'A3'))->toBe(1); // Digit not preceded by '-'
513+
expect(preg_match($regex, '-3'))->toBe(0); // Digit preceded by '-'
514+
});
515+
516+
test('addRawRegex method adds raw regex patterns correctly', function () {
517+
$builder = new BuilderPattern();
518+
$builder->addRawRegex('\d{3}-\d{2}-\d{4}'); // SSN pattern
519+
520+
$regex = $builder->getInputValidationPattern();
521+
expect(preg_match($regex, '123-45-6789'))->toBe(1);
522+
expect(preg_match($regex, '123456789'))->toBe(0);
523+
});
524+
525+
test('addRawNonCapturingGroup method adds and wraps raw regex in a non-capturing group', function () {
526+
$builder = new BuilderPattern();
527+
$builder->addRawNonCapturingGroup('\d+')->exact('A');
528+
529+
$regex = $builder->getInputValidationPattern();
530+
expect(preg_match($regex, '123A'))->toBe(1);
531+
expect(preg_match($regex, 'A123'))->toBe(0);
532+
});

0 commit comments

Comments
 (0)