Skip to content

Commit 06a2c63

Browse files
committed
1.0
1 parent eb97b54 commit 06a2c63

10 files changed

+309
-30
lines changed

.vscode/templates.code-snippets

+8-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"body": [
66
"<?php",
77
"",
8-
"namespace Chevere\\%namespace%;",
8+
"namespace Chevere\\Regex;",
99
"",
1010
"/**",
1111
" * Describes the component in charge of ${1:doing}.",
@@ -22,7 +22,7 @@
2222
"body": [
2323
"<?php",
2424
"",
25-
"namespace Chevere\\%namespace%;",
25+
"namespace Chevere\\Regex;",
2626
"",
2727
"final class $TM_FILENAME_BASE",
2828
"{",
@@ -36,7 +36,7 @@
3636
"body": [
3737
"<?php",
3838
"",
39-
"namespace Chevere\\%namespace%;",
39+
"namespace Chevere\\Regex;",
4040
"",
4141
"use Chevere\\Exceptions\\Core\\Exception;",
4242
"",
@@ -54,7 +54,7 @@
5454
"body": [
5555
"<?php",
5656
"",
57-
"namespace Chevere\\%namespace%;",
57+
"namespace Chevere\\Regex;",
5858
"",
5959
"trait $TM_FILENAME_BASE",
6060
"{",
@@ -68,7 +68,7 @@
6868
"body": [
6969
"<?php",
7070
"",
71-
"namespace Chevere\\%namespace%\\\\${TM_DIRECTORY/.*src\\/(([^\\/]*)(\\/)?)|(\\/)([^\\/]*)/$2${3:+.}${5:+.}$5/g};",
71+
"namespace Chevere\\Regex\\\\${TM_DIRECTORY/.*src\\/(([^\\/]*)(\\/)?)|(\\/)([^\\/]*)/$2${3:+.}${5:+.}$5/g};",
7272
"",
7373
"/**",
7474
" * Describes the component in charge of ${1:doing}.",
@@ -85,7 +85,7 @@
8585
"body": [
8686
"<?php",
8787
"",
88-
"namespace Chevere\\%namespace%\\\\${TM_DIRECTORY/.*src\\/(([^\\/]*)(\\/)?)|(\\/)([^\\/]*)/$2${3:+.}${5:+.}$5/g};",
88+
"namespace Chevere\\Regex\\\\${TM_DIRECTORY/.*src\\/(([^\\/]*)(\\/)?)|(\\/)([^\\/]*)/$2${3:+.}${5:+.}$5/g};",
8989
"",
9090
"final class $TM_FILENAME_BASE",
9191
"{",
@@ -99,7 +99,7 @@
9999
"body": [
100100
"<?php",
101101
"",
102-
"namespace Chevere\\%namespace%\\\\${TM_DIRECTORY/.*src\\/(([^\\/]*)(\\/)?)|(\\/)([^\\/]*)/$2${3:+.}${5:+.}$5/g};",
102+
"namespace Chevere\\Regex\\\\${TM_DIRECTORY/.*src\\/(([^\\/]*)(\\/)?)|(\\/)([^\\/]*)/$2${3:+.}${5:+.}$5/g};",
103103
"",
104104
"use Chevere\\Exceptions\\Core\\Exception;",
105105
"",
@@ -117,7 +117,7 @@
117117
"body": [
118118
"<?php",
119119
"",
120-
"namespace Chevere\\%namespace%\\\\${TM_DIRECTORY/.*src\\/(([^\\/]*)(\\/)?)|(\\/)([^\\/]*)/$2${3:+.}${5:+.}$5/g};",
120+
"namespace Chevere\\Regex\\\\${TM_DIRECTORY/.*src\\/(([^\\/]*)(\\/)?)|(\\/)([^\\/]*)/$2${3:+.}${5:+.}$5/g};",
121121
"",
122122
"trait $TM_FILENAME_BASE",
123123
"{",

README.md

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
# %namespace%
1+
# Regex
22

33
> 🔔 Subscribe to the [newsletter](https://chv.to/chevere-newsletter) to don't miss any update regarding Chevere.
44
55
![Chevere](chevere.svg)
66

7-
[![Build](https://img.shields.io/github/actions/workflow/status/chevere/reponame/test.yml?branch=%branch%&style=flat-square)](https://github.com/chevere/reponame/actions)
8-
![Code size](https://img.shields.io/github/languages/code-size/chevere/reponame?style=flat-square)
9-
[![Apache-2.0](https://img.shields.io/github/license/chevere/reponame?style=flat-square)](LICENSE)
7+
[![Build](https://img.shields.io/github/actions/workflow/status/chevere/regex/test.yml?branch=1.0&style=flat-square)](https://github.com/chevere/regex/actions)
8+
![Code size](https://img.shields.io/github/languages/code-size/chevere/regex?style=flat-square)
9+
[![Apache-2.0](https://img.shields.io/github/license/chevere/regex?style=flat-square)](LICENSE)
1010
[![PHPStan](https://img.shields.io/badge/PHPStan-level%209-blueviolet?style=flat-square)](https://phpstan.org/)
11-
[![Mutation testing badge](https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fchevere%2Freponame%2F%branch%)](https://dashboard.stryker-mutator.io/reports/github.com/chevere/reponame/%branch%)
12-
13-
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=chevere_reponame&metric=alert_status)](https://sonarcloud.io/dashboard?id=chevere_reponame)
14-
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=chevere_reponame&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=chevere_reponame)
15-
[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=chevere_reponame&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=chevere_reponame)
16-
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=chevere_reponame&metric=security_rating)](https://sonarcloud.io/dashboard?id=chevere_reponame)
17-
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=chevere_reponame&metric=coverage)](https://sonarcloud.io/dashboard?id=chevere_reponame)
18-
[![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=chevere_reponame&metric=sqale_index)](https://sonarcloud.io/dashboard?id=chevere_reponame)
19-
[![CodeFactor](https://www.codefactor.io/repository/github/chevere/reponame/badge)](https://www.codefactor.io/repository/github/chevere/reponame)
20-
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/b956754f8ff04aaa9ca24a6e4cc21661)](https://app.codacy.com/gh/chevere/reponame/dashboard)
11+
[![Mutation testing badge](https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fchevere%2Fregex%2F1.0)](https://dashboard.stryker-mutator.io/reports/github.com/chevere/regex/1.0)
12+
13+
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=chevere_regex&metric=alert_status)](https://sonarcloud.io/dashboard?id=chevere_regex)
14+
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=chevere_regex&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=chevere_regex)
15+
[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=chevere_regex&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=chevere_regex)
16+
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=chevere_regex&metric=security_rating)](https://sonarcloud.io/dashboard?id=chevere_regex)
17+
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=chevere_regex&metric=coverage)](https://sonarcloud.io/dashboard?id=chevere_regex)
18+
[![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=chevere_regex&metric=sqale_index)](https://sonarcloud.io/dashboard?id=chevere_regex)
19+
[![CodeFactor](https://www.codefactor.io/repository/github/chevere/regex/badge)](https://www.codefactor.io/repository/github/chevere/regex)
20+
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/b956754f8ff04aaa9ca24a6e4cc21661)](https://app.codacy.com/gh/chevere/regex/dashboard)
2121

2222
## Documentation
2323

composer.json

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"name": "chevere/reponame",
3-
"description": "A chevere reponame package",
2+
"name": "chevere/regex",
3+
"description": "A chevere regex package",
44
"homepage": "https://chevere.org",
55
"type": "library",
66
"license": "Apache-2.0",
@@ -12,19 +12,18 @@
1212
}
1313
],
1414
"require": {
15-
"chevere/chevere": "^3.0"
15+
"php": "^8.1",
16+
"chevere/message": "^0.1.0",
17+
"thecodingmachine/safe": "^2.5"
1618
},
1719
"require-dev": {
1820
"phpstan/phpstan": "^1.9",
1921
"phpunit/phpunit": "^9.5",
2022
"symplify/easy-coding-standard": "^11.1"
2123
},
2224
"autoload": {
23-
"files": [
24-
"src/functions.php"
25-
],
2625
"psr-4": {
27-
"Chevere\\%namespace%\\": "src/"
26+
"Chevere\\Regex\\": "src/"
2827
}
2928
},
3029
"autoload-dev": {

sonar-project.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
sonar.projectKey=chevere_reponame
1+
sonar.projectKey=chevere_regex
22
sonar.organization=chevere
33
sonar.host.url=https://sonarcloud.io
44
sonar.sourceEncoding=UTF-8

src/.git-keep

Whitespace-only changes.

src/Exceptions/NoMatchException.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Chevere.
5+
*
6+
* (c) Rodolfo Berrios <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Chevere\Regex\Exceptions;
15+
16+
use Exception;
17+
18+
/**
19+
* Exception thrown when regular expression doesn't match.
20+
*/
21+
final class NoMatchException extends Exception
22+
{
23+
}

src/Interfaces/RegexInterface.php

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Chevere.
5+
*
6+
* (c) Rodolfo Berrios <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Chevere\Regex\Interfaces;
15+
16+
use Stringable;
17+
18+
/**
19+
* Describes the component in charge of interacting with PCRE - Perl Compatible Regular Expressions.
20+
*/
21+
interface RegexInterface extends Stringable
22+
{
23+
public const ERRORS = [
24+
PREG_NO_ERROR => 'PREG_NO_ERROR',
25+
PREG_INTERNAL_ERROR => 'PREG_INTERNAL_ERROR',
26+
PREG_BACKTRACK_LIMIT_ERROR => 'PREG_BACKTRACK_LIMIT_ERROR',
27+
PREG_RECURSION_LIMIT_ERROR => 'PREG_RECURSION_LIMIT_ERROR',
28+
PREG_BAD_UTF8_ERROR => 'PREG_BAD_UTF8_ERROR',
29+
PREG_BAD_UTF8_OFFSET_ERROR => 'PREG_BAD_UTF8_OFFSET_ERROR',
30+
PREG_JIT_STACKLIMIT_ERROR => 'PREG_JIT_STACKLIMIT_ERROR',
31+
];
32+
33+
/**
34+
* Provides access to the the regex string without delimiters.
35+
*/
36+
public function noDelimiters(): string;
37+
38+
/**
39+
* Provides access to the regex string without delimiters and anchors.
40+
*/
41+
public function noDelimitersNoAnchors(): string;
42+
43+
/**
44+
* @return array<int, string>
45+
*/
46+
public function match(string $string): array;
47+
48+
/**
49+
* @return array<array<int, string>>
50+
*/
51+
public function matchAll(string $string): array;
52+
53+
public function assertMatch(string $string): void;
54+
55+
public function assertMatchAll(string $string): void;
56+
}

src/Regex.php

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Chevere.
5+
*
6+
* (c) Rodolfo Berrios <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Chevere\Regex;
15+
16+
use Chevere\Regex\Exceptions\NoMatchException;
17+
use Chevere\Regex\Interfaces\RegexInterface;
18+
use InvalidArgumentException;
19+
use RuntimeException;
20+
use Safe\Exceptions\PcreException;
21+
use Throwable;
22+
use function Chevere\Message\message;
23+
use function Safe\preg_match;
24+
use function Safe\preg_match_all;
25+
26+
final class Regex implements RegexInterface
27+
{
28+
private string $noDelimiters;
29+
30+
private string $noDelimitersNoAnchors;
31+
32+
/**
33+
* @throws InvalidArgumentException
34+
*/
35+
public function __construct(
36+
private string $pattern
37+
) {
38+
$this->assertRegex();
39+
$delimiter = $this->pattern[0];
40+
$this->noDelimiters = trim($this->pattern, $delimiter);
41+
$this->noDelimitersNoAnchors = strval(preg_replace('#^\^(.*)\$$#', '$1', $this->noDelimiters));
42+
}
43+
44+
public function __toString(): string
45+
{
46+
return $this->pattern;
47+
}
48+
49+
public function noDelimiters(): string
50+
{
51+
return $this->noDelimiters;
52+
}
53+
54+
public function noDelimitersNoAnchors(): string
55+
{
56+
return $this->noDelimitersNoAnchors;
57+
}
58+
59+
public function match(string $string): array
60+
{
61+
try {
62+
$match = preg_match($this->pattern, $string, $matches);
63+
}
64+
// @codeCoverageIgnoreStart
65+
catch (PcreException $e) {
66+
throw new RuntimeException(
67+
(string) message('Unable to `%s%`', s: 'preg_match')
68+
);
69+
}
70+
// @codeCoverageIgnoreEnd
71+
72+
return $match === 1 ? $matches : [];
73+
}
74+
75+
public function assertMatch(string $string): void
76+
{
77+
if (! $this->match($string)) {
78+
throw new NoMatchException(
79+
(string) message(
80+
'String `%string%` does not match regex `%pattern%`',
81+
pattern: $this->pattern,
82+
string: $string,
83+
),
84+
100
85+
);
86+
}
87+
}
88+
89+
public function matchAll(string $string): array
90+
{
91+
try {
92+
$match = preg_match_all($this->pattern, $string, $matches);
93+
}
94+
// @codeCoverageIgnoreStart
95+
catch (PcreException $e) {
96+
throw new RuntimeException(
97+
(string) message('Unable to `%s%`', s: 'preg_match_all')
98+
);
99+
}
100+
// @codeCoverageIgnoreEnd
101+
102+
return $match === 1 ? $matches : [];
103+
}
104+
105+
public function assertMatchAll(string $string): void
106+
{
107+
if (! $this->matchAll($string)) {
108+
throw new NoMatchException(
109+
(string) message(
110+
'String `%string%` does not match all regex `%pattern%`',
111+
pattern: $this->pattern,
112+
string: $string,
113+
),
114+
110
115+
);
116+
}
117+
}
118+
119+
private function assertRegex(): void
120+
{
121+
try {
122+
preg_match($this->pattern, '');
123+
} catch (Throwable $e) {
124+
throw new InvalidArgumentException(
125+
previous: $e,
126+
message: (string) message(
127+
'Invalid regex string `%regex%` provided [%preg%]',
128+
regex: $this->pattern,
129+
preg: static::ERRORS[preg_last_error()],
130+
)
131+
);
132+
}
133+
}
134+
}

tests/.git-keep

Whitespace-only changes.

0 commit comments

Comments
 (0)