Skip to content

Commit cd6ebc2

Browse files
authored
Merge pull request #4 from MaestroError/documentation-and-examples
Documentation and examples
2 parents 31d58cf + a915fc9 commit cd6ebc2

File tree

10 files changed

+983
-288
lines changed

10 files changed

+983
-288
lines changed

README.md

Lines changed: 342 additions & 35 deletions
Large diffs are not rendered by default.

STRUCTURE.md

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
# EloquentRegex Structure
2+
3+
EloquentRegex offers a fluent and intuitive interface for Laravel developers to construct and execute regular expressions (regex) with ease. This document outlines the core components and functionalities of the EloquentRegex package, including ready-to-use patterns, custom pattern creation, and the use of options for added assertions and filtering. The primary purpose of the document is to clarify the inner workings and help you to understand the package better.
4+
5+
### Table of Contents
6+
7+
- [EloquentRegex Structure](#eloquentregex-structure)
8+
- [Ready-to-Use Patterns](#ready-to-use-patterns)
9+
- [Custom Patterns](#custom-patterns)
10+
- [Starting Points](#starting-points)
11+
- [Options](#options)
12+
- [Applying Options](#applying-options)
13+
- [Options as Filters](#options-as-filters)
14+
- [Options in Custom Patterns](#options-in-custom-patterns)
15+
- [Regex Flags](#regex-flags)
16+
- [Usage Structure](#usage-structure)
17+
- [Conclusion](#conclusion)
18+
19+
## Ready-to-Use Patterns
20+
21+
The inclusion of ready-to-use patterns for common formats like Email, URL, and IP addresses significantly streamlines validation tasks. These patterns are a testament to EloquentRegex's goal of providing developers with a toolkit that simplifies common regex tasks, making code more readable and maintainable. By encapsulating the complexity of regex syntax for these common use cases, EloquentRegex enables developers to perform validations and extractions without needing to manually craft and test these patterns. These patterns can be used directly with minimal setup:
22+
23+
```php
24+
EloquentRegex::source("[email protected]")->email()->check();
25+
```
26+
27+
They are defined in `src\Patterns` and I tried a lot to make pattern creation process as easy as possible. Here you can check example pattern:
28+
29+
```php
30+
<?php
31+
32+
namespace Maestroerror\EloquentRegex\Patterns;
33+
34+
use Maestroerror\EloquentRegex\Patterns\BasePattern;
35+
use Maestroerror\EloquentRegex\Traits\Pattern;
36+
37+
class EmailPattern extends BasePattern {
38+
39+
use Pattern;
40+
41+
// Regex
42+
protected string $pattern = "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}";
43+
44+
// Method name, which will be used to apply this pattern
45+
public static string $name = "email";
46+
47+
// Available arguments (option names)
48+
public static array $args = [
49+
"maxLength", // First argument
50+
"onlyDomains", // Second argument
51+
"onlyExtensions", // Third argument...
52+
];
53+
54+
// Options applied by default
55+
public static array $defaultOptions = [
56+
"minLength" => 5
57+
];
58+
}
59+
60+
```
61+
62+
All available patterns are registered in `src\Builder.php`, inside `$patterns` property
63+
64+
## Custom Patterns
65+
66+
_Custom patterns allow for detailed and specific regex definitions._
67+
68+
The ability to create custom patterns using methods is central to EloquentRegex's value proposition. This feature leverages a fluent API, allowing developers to construct complex regex expressions through a series of method calls. Each method call builds upon the previous one, enabling the construction of regex patterns in a piecewise, understandable manner. This approach not only makes the creation of regex patterns more intuitive but also enhances code readability by making the patterns' purposes and structures clear at a glance.
69+
70+
```php
71+
EloquentRegex::start("#hello #world This is a #test")->hash()->text()->get();
72+
```
73+
74+
This functionality mainly depends on the `src\Patterns\BuilderPattern.php`, which technichally is one of the patterns in the system, just haven't predefined regex and allows you to build regex pattern using the chainable methods.
75+
76+
### Starting Points
77+
78+
Custom pattern can be initiated with `start` or `customPattern` methods, which are interchangeable and mark the beginning of a custom pattern creation. The `source` and the `string` methods are starting point for ready-to-use patterns, while it returns the main `Builder` class, you can "switch" to the custom pattern from it, of course, if you preffer syntax like this:
79+
80+
```php
81+
EloquentRegex::source("#hello #world This is a #test")->start()->hash()->text()->end()->get(); // end() method is optional here
82+
```
83+
84+
## Options
85+
86+
Options provide a powerful way to fine-tune patterns. They can be specific to the pattern or applied globally as extra assertions. Patterns define their arguments for easy option application.
87+
88+
It is quiet easy to add a new option class, mainly it needs 2 methods `validate` and `build`. Validate method is used for validation and build method is optional for cases, where option uses regex for validation (Yes, some options are validating input using PHP methods, some Regex pattern and some both, it depends on the Option). Also, option classes need the "option methods", which should be registered as separated options in the `src\OptionsMapper.php` class. For example:
89+
90+
```php
91+
<?php
92+
93+
namespace Maestroerror\EloquentRegex\Options;
94+
95+
use Maestroerror\EloquentRegex\Contracts\OptionContract;
96+
use Maestroerror\EloquentRegex\Traits\ValidateUsingRegexTrait;
97+
98+
class FileOption implements OptionContract {
99+
100+
use ValidateUsingRegexTrait;
101+
102+
private $isFile = false;
103+
private $isDirectory = 0;
104+
private $fileExtension = null;
105+
private $validateUsingRegex = true;
106+
107+
// Validates input using regex if "validateUsingRegex" is true, or php blocks otherwise
108+
public function validate(string $input): bool {
109+
if ($this->validateUsingRegex) {
110+
return $this->validateUsingRegex($input);
111+
}
112+
113+
if ($this->isFile) {
114+
if ($this->fileExtension) {
115+
if (!preg_match("/\." . preg_quote($this->fileExtension) . "$/", $input)) {
116+
return false;
117+
}
118+
} elseif (!preg_match("/\.[a-zA-Z0-9]+$/", $input)) {
119+
return false;
120+
}
121+
}
122+
123+
if ($this->isDirectory) {
124+
if (substr($input, -1) != '/') {
125+
return false;
126+
}
127+
}
128+
129+
return true;
130+
}
131+
132+
// Builds regex pattern
133+
public function build(): string {
134+
if ($this->isFile) {
135+
if ($this->fileExtension) {
136+
return "[A-Za-z0-9\\/:\.\-\\\\]*\." . preg_quote($this->fileExtension);
137+
} else {
138+
return "[A-Za-z0-9\\/:\.\-\\\\]*\.[a-zA-Z0-9]+";
139+
}
140+
}
141+
142+
if ($this->isDirectory) {
143+
return "(?:[a-zA-Z0-9\\/:\-\\\\]+)+";
144+
}
145+
146+
return '.*';
147+
}
148+
149+
// "option methods":
150+
151+
public function isFile(string|null $extension = null) {
152+
$this->isFile = true;
153+
$this->fileExtension = $extension;
154+
return $this;
155+
}
156+
157+
public function isDirectory(int $check = 1) {
158+
$this->isDirectory = $check;
159+
return $this;
160+
}
161+
}
162+
```
163+
164+
Later, the "option methods" are registered in OptionsMapper class:
165+
166+
```php
167+
/**
168+
* @var array Mapping of option names to their corresponding class and method.
169+
*/
170+
public static array $optionMethods = [
171+
// Other options...
172+
"isFile" => [FileOption::class, "isFile"],
173+
"isDirectory" => [FileOption::class, "isDirectory"],
174+
// Other options...
175+
];
176+
```
177+
178+
_Note: option methods **should** have only one argument._
179+
180+
### Applying Options
181+
182+
- Via Arguments: Directly passing parameters defined by the pattern class in $args property.
183+
184+
```php
185+
EloquentRegex::source("StrongP@ssw0rd")->password(8, 1, 1, 1)->check();
186+
```
187+
188+
- Via Callback: Using a closure to apply multiple options dynamically (recomended way).
189+
190+
```php
191+
EloquentRegex::source("StrongP@ssw0rd")->password(function($pattern) {
192+
return $pattern->minLength(8)->minUppercase(1)->minNumbers(1)->minSpecialChars(1);
193+
})->check();
194+
```
195+
196+
- Via Array: Applying options using an associative array.
197+
198+
```php
199+
EloquentRegex::source("[email protected]")->email(['onlyExtensions' => ['com', 'org']])->check(); // true
200+
```
201+
202+
_Note: argument includes pattern-specific option in predefined manner, but while using **array** or **callback** you can apply **any option** to **any pattern**_
203+
204+
### Options as Filters
205+
206+
Options can also act as filters during extraction (`get()`), ensuring only matches that meet specific criteria are returned.
207+
208+
```php
209+
EloquentRegex::source("Visa: 4111 1111 1111 1111, MasterCard: 5500 0000 0000 0004, Amex: 3400 000000 00009")
210+
->creditCardNumber("visa, amex")->get();
211+
// Returns only Visa and Amex card numbers
212+
213+
```
214+
215+
### Options in Custom Patterns
216+
217+
Sure! You can apply option to your custom pattern using the `end(callback|array $config)` method:
218+
219+
```php
220+
EloquentRegex::customPattern("Users: user_123, JohnDoe_99")
221+
->alphanumeric()
222+
->underscore()
223+
->digitsRange(0, 5)
224+
->end(["maxLength" => 8]) // Applied maxLength option
225+
->get(); // Returns array including "user_123" within
226+
```
227+
228+
### Regex Flags
229+
230+
Regex flags are applied outside the options scope through easy-to-use methods, allowing for global pattern modifiers like Unicode support.
231+
232+
```php
233+
// Regex flags can be applied only after the end() method
234+
EloquentRegex::start("მზადაა #1 ✔️ და #2 ✔️")->wordCharRange(0, 2)->end()->asUnicode()->get();
235+
```
236+
237+
## Usage structure
238+
239+
Here you can check the usage structure:
240+
241+
```
242+
[Initiator][Pattern][?Optional][Action]
243+
```
244+
245+
- **Initiator** - Sets target string and returns `Builder` for ready-to-use patterns or `BuilderPattern` for building custom patterns (ex: `EloquentRegex::source`)
246+
- **Pattern** - Method for ready to use pattern like `email`, `url`, `filePath` and etc. Or custom pattern created using the `BuilderPattern` methods.
247+
- **?Optional** - Any optional methods like: regex expression flags and `end` method
248+
- **Action** - Final method which performs some action like: `get`, `check`, `toRegex` and etc.
249+
250+
_Note: Action methods have replicas in `BuilderPattern` to ensure that `end` method remains optional_
251+
252+
# Conclusion
253+
254+
EloquentRegex simplifies the creation and execution of regular expressions in Laravel applications. Through its intuitive API, developers can quickly implement complex regex operations with precision and flexibility. Whether utilizing ready-to-use patterns for common tasks or crafting custom solutions with dynamic options, EloquentRegex enhances productivity and code clarity.

src/Builder.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,20 +186,22 @@ public function toRegex(): string {
186186
}
187187

188188
// In cases when pattern doesn't allow setting the options (like BuilderPattern)
189-
public function setOptions(array|callable $config): void {
189+
public function setOptions(array|callable $config): self {
190190
// Check if the pattern is set
191191
if (!$this->patternIsSet()) {
192192
throw new \LogicException("Pattern must be set before setting options.");
193193
}
194194

195195
// Handle options array scenario
196-
if (is_array($config)) {
196+
if (is_array($config) && !empty($config)) {
197197
$this->processConfigArray($config);
198198
}
199199
// Handle callback scenario
200200
else if (is_callable($config)) {
201201
$this->processCallback($config);
202202
}
203+
204+
return $this;
203205
}
204206

205207
/**

src/Contracts/BuilderContract.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public function toRegex(): string;
5959
* @param array|callable $config An array of options (optionName => value (arg)) or a callback function to configure options.
6060
* @return void
6161
*/
62-
public function setOptions(array|callable $config): void;
62+
public function setOptions(array|callable $config): self;
6363

6464
/**
6565
* Registers a single pattern in the Builder.

0 commit comments

Comments
 (0)