Skip to content
This repository was archived by the owner on Mar 29, 2024. It is now read-only.

Commit 7895d85

Browse files
committed
Add support for types groupping and arrays shortcut, closes #6
1 parent 344583c commit 7895d85

File tree

3 files changed

+318
-16
lines changed

3 files changed

+318
-16
lines changed

src/Extractors/ExtractorDefinitionBuilder.php

Lines changed: 119 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,49 @@ class ExtractorDefinitionBuilder implements ExtractorDefinitionBuilderInterface
2727
/**
2828
* @var string
2929
*/
30-
protected $type_regexp = '/^((?<name>[-_\w]+)(?:\s*\(\s*(?<param>(?-3)*|[\w\\\\]+)\s*\))?(?:\s*\|\s*(?<alt>(?-4)))?)$/';
30+
protected $type_regexp = '/
31+
^
32+
(
33+
(?<name>
34+
[-_\w]*
35+
)
36+
(?:
37+
\s*
38+
(?<group>
39+
\(
40+
\s*
41+
(?<param>
42+
(?-4)*
43+
|
44+
[\w\\\\]+
45+
)
46+
\s*
47+
\)
48+
)
49+
)?
50+
(?:
51+
\s*
52+
(?<arr>(?:\s*\[\s*\]\s*)+)
53+
)?
54+
(?:
55+
\s*
56+
\|
57+
\s*
58+
(?<alt>(?-6))
59+
)?
60+
)
61+
$
62+
/xi';
63+
64+
protected $type_regexp2 = '/
65+
^
66+
(?:((\w+\b(?:\(.*\))?(?:\s*\[\s*\])?)(?:\s*\|\s*(?-1))*))
67+
|
68+
(?:\(\s*(?-2)\s*\)(?:\s*\[\s*\])?)
69+
|
70+
(\[\s*\])
71+
$
72+
/xi';
3173

3274
/**
3375
* {@inheritdoc}
@@ -40,32 +82,53 @@ public function build(string $definition): ExtractorDefinitionInterface
4082
throw new ExtractorDefinitionBuilderException('Definition must be non-empty string');
4183
}
4284

43-
if (preg_match($this->type_regexp, $definition, $matches)) {
44-
return $this->buildExtractor($matches['name'], $matches['param'] ?? null, $matches['alt'] ?? null);
85+
try {
86+
if (preg_match($this->type_regexp, $definition, $matches)) {
87+
$extractor = $this->buildExtractor($matches['name'], $matches['param'] ?? '', $matches['alt'] ?? '', $this->getDepth($matches), $this->hasGroups($matches));
88+
89+
return $extractor;
90+
}
91+
} catch (ExtractorDefinitionBuilderException $e) {
92+
// We don't care about what specific issue we hit inside,
93+
// for API user it means that the definition is invalid
4594
}
4695

4796
throw new ExtractorDefinitionBuilderException("Unable to parse definition: '{$definition}'");
4897
}
4998

5099
/**
51-
* @param string $name
100+
* @param string $name
52101
* @param null|string $param
53102
* @param null|string $alt_definitions
103+
* @param int $depth
104+
* @param bool $groups
54105
*
55106
* @return ExtractorDefinitionInterface
56107
* @throws ExtractorDefinitionBuilderException
57108
*/
58-
protected function buildExtractor(string $name, ?string $param, ?string $alt_definitions): ExtractorDefinitionInterface
109+
protected function buildExtractor(string $name, string $param, string $alt_definitions, int $depth, bool $groups): ExtractorDefinitionInterface
59110
{
60111
$next = null;
61112

62-
if ($param && preg_match($this->type_regexp, $param, $matches)) {
63-
$next = $this->buildExtractor($matches['name'], $matches['param'] ?? null, $matches['alt'] ?? null);
113+
if ('' !== $param && preg_match($this->type_regexp, $param, $matches)) {
114+
$next = $this->buildExtractor($matches['name'], $matches['param'] ?? '', $matches['alt'] ?? '', $this->getDepth($matches), $this->hasGroups($matches));
115+
}
116+
117+
if ($name) {
118+
$definition = new PlainExtractorDefinition($name, $next);
119+
} else {
120+
$definition = $next;
121+
}
122+
123+
if ($depth > 0) {
124+
$definition = $this->buildArrayDefinition($definition, $depth, $groups);
64125
}
65126

66-
$definition = new PlainExtractorDefinition($name, $next);
127+
if (!$definition) {
128+
throw new ExtractorDefinitionBuilderException('Empty group is not allowed');
129+
}
67130

68-
if ($alt_definitions) {
131+
if ('' !== $alt_definitions) {
69132
$definition = $this->buildVariableDefinition($definition, $alt_definitions);
70133
}
71134

@@ -74,7 +137,7 @@ protected function buildExtractor(string $name, ?string $param, ?string $alt_def
74137

75138
/**
76139
* @param PlainExtractorDefinitionInterface $definition
77-
* @param string $alt_definitions
140+
* @param string $alt_definitions
78141
*
79142
* @return VariableExtractorDefinition
80143
* @throws ExtractorDefinitionBuilderException
@@ -83,19 +146,61 @@ protected function buildVariableDefinition(PlainExtractorDefinitionInterface $de
83146
{
84147
$alt = [$definition];
85148

86-
while ($alt_definitions && preg_match($this->type_regexp, $alt_definitions, $matches)) {
149+
while ('' !== $alt_definitions && preg_match($this->type_regexp, $alt_definitions, $matches)) {
87150
// build alt
88-
$alt[] = $this->buildExtractor($matches['name'], $matches['param'] ?? null, null);
151+
$alt[] = $this->buildExtractor($matches['name'], $matches['param'] ?? '', '', $this->getDepth($matches), $this->hasGroups($matches));
89152

90-
$alt_definitions = $matches['alt'] ?? null;
153+
$alt_definitions = trim($matches['alt'] ?? '');
91154
}
92155

93-
if ($alt_definitions) {
156+
if ('' !== $alt_definitions) {
157+
// UNEXPECTED
94158
// this should not be possible, but just in case we will ever get here
95159
throw new ExtractorDefinitionBuilderException('Invalid varying definition');
96160
}
97161

98162
return new VariableExtractorDefinition(...$alt);
99163
}
100164

165+
/**
166+
* @param null|ExtractorDefinitionInterface $definition
167+
* @param int $depth
168+
* @param bool $groups
169+
*
170+
* @return ExtractorDefinitionInterface
171+
* @throws ExtractorDefinitionBuilderException
172+
*/
173+
protected function buildArrayDefinition(?ExtractorDefinitionInterface $definition, int $depth, bool $groups): ExtractorDefinitionInterface
174+
{
175+
if (!$definition && $groups) {
176+
throw new ExtractorDefinitionBuilderException('Empty group is not allowed');
177+
}
178+
179+
while ($depth) {
180+
$depth--;
181+
// arrayed definition
182+
$definition = new PlainExtractorDefinition('[]', $definition);
183+
}
184+
185+
return $definition;
186+
}
187+
188+
/**
189+
* @param array $matches
190+
*
191+
* @return int
192+
*/
193+
private function getDepth(array $matches): int
194+
{
195+
if (!isset($matches['arr']) || '' === $matches['arr']) {
196+
return 0;
197+
}
198+
199+
return substr_count($matches['arr'], '[');
200+
}
201+
202+
private function hasGroups(array $matches): bool
203+
{
204+
return isset($matches['group']) && '' !== $matches['group'];
205+
}
101206
}

src/Specs/Builder/ParameterSpecBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class ParameterSpecBuilder implements ParameterSpecBuilderInterface
5656
\s*
5757
\:
5858
\s*
59-
(?<type>(\w+\b(?:\(.*\))?)(?:\s*\|\s*(?-1))*)
59+
(?<type>(\w*(?:\(.*\))?(?:\[\s*\])?)(?:\s*\|\s*(?-1))*)
6060
\s*
6161
)?
6262
$

0 commit comments

Comments
 (0)