Skip to content

Commit 25adb82

Browse files
authored
perf(view): improve view component discovery performance (#1191)
1 parent d6a7d92 commit 25adb82

File tree

6 files changed

+60
-28
lines changed

6 files changed

+60
-28
lines changed

packages/support/src/Regex/functions.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,21 +77,25 @@ function get_all_matches(
7777
}
7878

7979
/**
80-
* Returns the specified match of `$pattern` in `$subject`. If no match is specified, returns the first group.
80+
* Returns the specified match of `$pattern` in `$subject`. If no match is specified, returns the whole matching array.
8181
*
8282
* @param non-empty-string $pattern The pattern to match against.
8383
* @param 0|256|512|768 $flags
8484
*/
8585
function get_match(
8686
Stringable|string $subject,
8787
Stringable|string $pattern,
88-
array|Stringable|int|string $match = 1,
88+
null|array|Stringable|int|string $match = null,
8989
mixed $default = null,
9090
int $flags = 0,
9191
int $offset = 0,
9292
): null|int|string|array {
9393
$result = get_matches($subject, $pattern, false, $flags, $offset);
9494

95+
if ($match === null) {
96+
return $result;
97+
}
98+
9599
if (is_array($match)) {
96100
return arr($result)
97101
->filter(fn ($_, string|int $key) => in_array($key, $match, strict: false)) // @mago-expect strictness/require-strict-behavior

packages/support/tests/Regex/FunctionsTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public function test_get_match(): void
8585
{
8686
$this->assertSame('10', get_match('10-abc', '/(?<id>\d+)-.*/', match: 'id'));
8787
$this->assertSame('10', get_match('10-abc', '/(\d+)-.*/', match: 1));
88-
$this->assertSame('10', get_match('10-abc', '/(\d+)-.*/'));
88+
$this->assertSame([0 => '10-abc', 1 => '10'], get_match('10-abc', '/(\d+)-.*/'));
8989
$this->assertSame('10-abc', get_match('10-abc', '/\d+-.*/', match: 0));
9090
$this->assertSame(null, get_match('10-abc', '/\d+-.*/', match: 1));
9191

packages/view/src/Elements/ElementFactory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Tempest\Container\Container;
88
use Tempest\Core\AppConfig;
99
use Tempest\View\Attributes\PhpAttribute;
10+
use Tempest\View\Components\AnonymousViewComponent;
1011
use Tempest\View\Components\DynamicViewComponent;
1112
use Tempest\View\Element;
1213
use Tempest\View\Parser\TempestViewCompiler;

packages/view/src/Parser/TempestViewCompiler.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,9 @@ private function cleanupCompiled(string $compiled): string
200200
return $matches[0];
201201
}
202202

203-
$imports[$matches[0]] = $matches[0];
203+
$import = trim($matches[0]);
204+
205+
$imports[$import] = $import;
204206

205207
return '';
206208
});

packages/view/src/ViewComponentDiscovery.php

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Tempest\Discovery\DiscoveryLocation;
1010
use Tempest\Discovery\IsDiscovery;
1111
use Tempest\Reflection\ClassReflector;
12+
use Tempest\Support\Str\ImmutableString;
1213
use Tempest\View\Components\AnonymousViewComponent;
1314

1415
use function Tempest\Support\str;
@@ -43,35 +44,61 @@ public function discoverPath(DiscoveryLocation $location, string $path): void
4344
return;
4445
}
4546

46-
$fileName = str(pathinfo($path, PATHINFO_FILENAME))->before('.');
4747
$contents = str(file_get_contents($path))->ltrim();
4848

49-
preg_match(
50-
pattern: '/(?<header>(.|\n)*?)<x-component name="(?<name>[\w\-]+)">(?<view>(.|\n)*?)<\/x-component>/',
51-
subject: $contents->toString(),
52-
matches: $matches,
53-
);
54-
55-
if ($fileName->startsWith('x-') && ! isset($matches['name'])) {
56-
$this->discoveryItems->add($location, [
57-
$fileName->toString(),
58-
new AnonymousViewComponent(
59-
contents: $matches['view'] ?? $contents->toString(),
60-
file: $path,
61-
),
62-
]);
49+
$fileName = str(pathinfo($path, PATHINFO_FILENAME))->before('.');
6350

64-
return;
51+
if ($fileName->startsWith('x-')) {
52+
$this->registerFileComponent(
53+
location: $location,
54+
path: $path,
55+
fileName: $fileName,
56+
contents: $contents,
57+
);
58+
} elseif ($contents->contains('<x-component name="')) {
59+
$this->registerElementComponent(
60+
location: $location,
61+
path: $path,
62+
contents: $contents,
63+
);
6564
}
65+
}
6666

67-
if (! isset($matches['name'], $matches['header'])) {
68-
return;
69-
}
67+
private function registerElementComponent(DiscoveryLocation $location, string $path, ImmutableString $contents): void
68+
{
69+
$header = $contents
70+
->before('<x-component name="')
71+
->toString();
72+
73+
$name = $contents
74+
->afterFirst('<x-component name="')
75+
->before('"')
76+
->toString();
77+
78+
$view = $contents
79+
->afterFirst('<x-component name="' . $name . '">')
80+
->beforeLast('</x-component>')
81+
->toString();
82+
83+
$this->discoveryItems->add($location, [
84+
$name,
85+
new AnonymousViewComponent(
86+
contents: $header . $view,
87+
file: $path,
88+
),
89+
]);
90+
}
7091

92+
private function registerFileComponent(
93+
DiscoveryLocation $location,
94+
string $path,
95+
ImmutableString $fileName,
96+
ImmutableString $contents,
97+
): void {
7198
$this->discoveryItems->add($location, [
72-
$matches['name'],
99+
$fileName->toString(),
73100
new AnonymousViewComponent(
74-
contents: $matches['header'] . $matches['view'],
101+
contents: $contents->toString(),
75102
file: $path,
76103
),
77104
]);

tests/Integration/View/x-auto-registered-with-declaration.view.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,4 @@
33

44
?>
55

6-
<x-component name="x-auto-registered-with-declaration">
7-
<span>{{ to_title_case('hello world') }}</span>
8-
</x-component>
6+
<span>{{ to_title_case('hello world') }}</span>

0 commit comments

Comments
 (0)