Skip to content

Commit dcb8d9c

Browse files
authored
Fix custom namespaces (#100)
* Add failing test * Refactor componentNameToPath * Move fixtures * Fix namespace test * Refactor * Fix test
1 parent 1c75cd7 commit dcb8d9c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+62
-97
lines changed

src/BladeService.php

Lines changed: 19 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Illuminate\Support\Str;
77
use Illuminate\View\Compilers\BladeCompiler;
88
use Illuminate\View\Compilers\ComponentTagCompiler;
9+
use Illuminate\View\Factory;
910
use Livewire\Blaze\Compiler\DirectiveCompiler;
1011
use Livewire\Blaze\Support\LaravelRegex;
1112
use ReflectionClass;
@@ -16,6 +17,7 @@ class BladeService
1617

1718
public function __construct(
1819
public BladeCompiler $compiler,
20+
protected Factory $view,
1921
) {
2022
$this->tagCompiler = new ComponentTagCompiler(blade: $compiler);
2123
}
@@ -194,87 +196,29 @@ public function viewCacheInvalidationHook(callable $callback): void
194196
*/
195197
public function componentNameToPath($name): string
196198
{
197-
$viewFinder = app('view')->getFinder();
199+
$finder = $this->view->getFinder();
198200

199-
$reflection = new \ReflectionClass($this->compiler);
200-
$pathsProperty = $reflection->getProperty('anonymousComponentPaths');
201-
$paths = $pathsProperty->getValue($this->compiler) ?? [];
202-
203-
if (str_contains($name, '::')) {
204-
[$namespace, $componentName] = explode('::', $name, 2);
205-
$componentPath = str_replace('.', '/', $componentName);
206-
207-
foreach ($paths as $pathData) {
208-
if (isset($pathData['prefix']) && $pathData['prefix'] === $namespace) {
209-
$basePath = rtrim($pathData['path'], '/');
210-
211-
$fullPath = $basePath.'/'.$componentPath.'.blade.php';
212-
if (file_exists($fullPath)) {
213-
return $fullPath;
214-
}
215-
216-
$indexPath = $basePath.'/'.$componentPath.'/index.blade.php';
217-
if (file_exists($indexPath)) {
218-
return $indexPath;
219-
}
220-
221-
$lastSegment = basename($componentPath);
222-
$sameNamePath = $basePath.'/'.$componentPath.'/'.$lastSegment.'.blade.php';
223-
if (file_exists($sameNamePath)) {
224-
return $sameNamePath;
225-
}
226-
}
227-
}
228-
229-
try {
230-
$viewName = str_replace('::', '::components.', $name);
231-
return $viewFinder->find($viewName);
232-
} catch (\Exception $e) {
233-
try {
234-
return $viewFinder->find(str_replace('::', '::components.', $name).'.index');
235-
} catch (\Exception $e2) {
236-
return '';
237-
}
238-
}
201+
if (! is_null($guess = $this->guessAnonymousComponentUsingNamespaces($this->view, $name)) ||
202+
! is_null($guess = $this->guessAnonymousComponentUsingPaths($this->view, $name))) {
203+
return $finder->find($guess);
239204
}
240205

241-
$componentPath = str_replace('.', '/', $name);
242-
243-
foreach ($paths as $pathData) {
244-
if (! isset($pathData['prefix']) || $pathData['prefix'] === null) {
245-
$registeredPath = $pathData['path'] ?? $pathData;
246-
247-
if (is_string($registeredPath)) {
248-
$basePath = rtrim($registeredPath, '/');
206+
return '';
207+
}
249208

250-
$fullPath = $basePath.'/'.$componentPath.'.blade.php';
251-
if (file_exists($fullPath)) {
252-
return $fullPath;
253-
}
209+
protected function guessAnonymousComponentUsingNamespaces(Factory $viewFactory, string $component): string|null
210+
{
211+
$reflection = new \ReflectionClass($this->tagCompiler);
212+
$method = $reflection->getMethod('guessAnonymousComponentUsingNamespaces');
254213

255-
$indexPath = $basePath.'/'.$componentPath.'/index.blade.php';
256-
if (file_exists($indexPath)) {
257-
return $indexPath;
258-
}
214+
return $method->invoke($this->tagCompiler, $viewFactory, $component);
215+
}
259216

260-
$lastSegment = basename($componentPath);
261-
$sameNamePath = $basePath.'/'.$componentPath.'/'.$lastSegment.'.blade.php';
262-
if (file_exists($sameNamePath)) {
263-
return $sameNamePath;
264-
}
265-
}
266-
}
267-
}
217+
protected function guessAnonymousComponentUsingPaths(Factory $viewFactory, string $component): string|null
218+
{
219+
$reflection = new \ReflectionClass($this->tagCompiler);
220+
$method = $reflection->getMethod('guessAnonymousComponentUsingPaths');
268221

269-
try {
270-
return $viewFinder->find("components.{$name}");
271-
} catch (\Exception $e) {
272-
try {
273-
return $viewFinder->find("components.{$name}.index");
274-
} catch (\Exception $e2) {
275-
return '';
276-
}
277-
}
222+
return $method->invoke($this->tagCompiler, $viewFactory, $component);
278223
}
279-
280224
}

tests/BladeServiceTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
use Illuminate\Support\Facades\Blade;
4+
use Livewire\Blaze\BladeService;
5+
6+
test('componentNameToPath', function ($callback, $prefix, $name, $path) {
7+
$callback();
8+
9+
expect(app(BladeService::class)->componentNameToPath($prefix . $name))->toBe($path);
10+
})
11+
->with([
12+
'default path' => [fn () => null, 'dummy.'],
13+
'custom path' => [fn () => Blade::anonymousComponentPath(fixture_path('views/components/dummy')), ''],
14+
'custom path with prefix' => [fn () => Blade::anonymousComponentPath(fixture_path('views/components/dummy'), 'dummy'), 'dummy::'],
15+
'custom namespace' => [fn () => Blade::anonymousComponentNamespace('components.dummy', 'dummy'), 'dummy::'],
16+
])
17+
->with([
18+
'exact file' => ['foo', fixture_path('views/components/dummy/foo.blade.php')],
19+
'index file' => ['bar', fixture_path('views/components/dummy/bar/index.blade.php')],
20+
'directory name' => ['baz', fixture_path('views/components/dummy/baz/baz.blade.php')],
21+
]);

tests/Compiler/CompilerTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
$node = app(Parser::class)->parse($input)[0];
1111
$compiled = app(Compiler::class)->compile($node);
1212

13-
$path = fixture_path('components/input.blade.php');
13+
$path = fixture_path('views/components/input.blade.php');
1414
$hash = Utils::hash($path);
1515

1616
expect($compiled->render())->toEqualCollapsingWhitespace(join('', [
@@ -38,7 +38,7 @@
3838
$node = app(Parser::class)->parse($input)[0];
3939
$compiled = app(Compiler::class)->compile($node);
4040

41-
$path = fixture_path('components/card.blade.php');
41+
$path = fixture_path('views/components/card.blade.php');
4242
$hash = Utils::hash($path);
4343

4444
expect($compiled->render())->toEqualCollapsingWhitespace(join('', [

tests/Compiler/WrapperTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use Livewire\Blaze\BladeService;
77

88
test('wraps component templates into function definitions', function () {
9-
$path = fixture_path('components/input.blade.php');
9+
$path = fixture_path('views/components/input.blade.php');
1010
$source = file_get_contents($path);
1111
$hash = Utils::hash($path);
1212

@@ -31,7 +31,7 @@
3131
});
3232

3333
test('compiles aware props', function () {
34-
$path = fixture_path('components/input-aware.blade.php');
34+
$path = fixture_path('views/components/input-aware.blade.php');
3535
$source = file_get_contents($path);
3636
$hash = Utils::hash($path);
3737

tests/Folder/FoldableTest.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
$input = '<x-foldable.input :type="$type" />';
1212

1313
$node = app(Parser::class)->parse($input)[0];
14-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/input.blade.php')), app(BladeRenderer::class), app(BladeService::class));
14+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input.blade.php')), app(BladeRenderer::class), app(BladeService::class));
1515

1616
expect($foldable->fold())->toEqualCollapsingWhitespace(
1717
'<input type="{{ $type }}" >'
@@ -35,7 +35,7 @@
3535
;
3636

3737
$node = app(Parser::class)->parse($input)[0];
38-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/card.blade.php')), app(BladeRenderer::class), app(BladeService::class));
38+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/card.blade.php')), app(BladeRenderer::class), app(BladeService::class));
3939

4040
expect($foldable->fold())->toEqualCollapsingWhitespace(<<<'HTML'
4141
<div>
@@ -53,7 +53,7 @@
5353
$input = '<x-foldable.input :disabled="false" />';
5454

5555
$node = app(Parser::class)->parse($input)[0];
56-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/input.blade.php')), app(BladeRenderer::class), app(BladeService::class));
56+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input.blade.php')), app(BladeRenderer::class), app(BladeService::class));
5757

5858
expect($foldable->fold())->toEqualCollapsingWhitespace(
5959
'<input type="text" >'
@@ -64,7 +64,7 @@
6464
$input = '<x-foldable.input :disabled="null" />';
6565

6666
$node = app(Parser::class)->parse($input)[0];
67-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/input.blade.php')), app(BladeRenderer::class), app(BladeService::class));
67+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input.blade.php')), app(BladeRenderer::class), app(BladeService::class));
6868

6969
expect($foldable->fold())->toEqualCollapsingWhitespace(
7070
'<input type="text" >'
@@ -75,7 +75,7 @@
7575
$input = '<x-foldable.input-aware />';
7676

7777
$node = app(Parser::class)->parse($input)[0];
78-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/input-aware.blade.php')), app(BladeRenderer::class), app(BladeService::class));
78+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input-aware.blade.php')), app(BladeRenderer::class), app(BladeService::class));
7979

8080
$node->setParentsAttributes([
8181
'type' => new Attribute(
@@ -106,7 +106,7 @@
106106
),
107107
]);
108108

109-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/input-aware.blade.php')), app(BladeRenderer::class), app(BladeService::class));
109+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input-aware.blade.php')), app(BladeRenderer::class), app(BladeService::class));
110110

111111
expect($foldable->fold())->toEqualCollapsingWhitespace(
112112
'<input type="{{ $type }}" >'
@@ -117,7 +117,7 @@
117117
$input = '<x-foldable.input :readonly="$readonly" />';
118118

119119
$node = app(Parser::class)->parse($input)[0];
120-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/input.blade.php')), app(BladeRenderer::class), app(BladeService::class));
120+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input.blade.php')), app(BladeRenderer::class), app(BladeService::class));
121121

122122
expect($foldable->fold())->toEqualCollapsingWhitespace(
123123
sprintf('<input %s type="text" >', join('', [
@@ -134,7 +134,7 @@
134134
$node = app(Parser::class)->parse($input)[0];
135135
$node->hasAwareDescendants = true;
136136

137-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/card.blade.php')), app(BladeRenderer::class), app(BladeService::class));
137+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/card.blade.php')), app(BladeRenderer::class), app(BladeService::class));
138138

139139
expect($foldable->fold())->toEqualCollapsingWhitespace(join('', [
140140
'<?php $__blaze->pushData([\'name\' => \'John\']); $__env->pushConsumableComponentData([\'name\' => \'John\']); ?>',
@@ -149,7 +149,7 @@
149149
$node = app(Parser::class)->parse($input)[0];
150150
$node->hasAwareDescendants = true;
151151

152-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/card.blade.php')), app(BladeRenderer::class), app(BladeService::class));
152+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/card.blade.php')), app(BladeRenderer::class), app(BladeService::class));
153153

154154
expect($foldable->fold())->toEqualCollapsingWhitespace(join('', [
155155
'<?php $__blaze->pushData([\'name\' => $name]); $__env->pushConsumableComponentData([\'name\' => $name]); ?>',
@@ -164,7 +164,7 @@
164164
$node = app(Parser::class)->parse($input)[0];
165165
$node->hasAwareDescendants = true;
166166

167-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/card.blade.php')), app(BladeRenderer::class), app(BladeService::class));
167+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/card.blade.php')), app(BladeRenderer::class), app(BladeService::class));
168168

169169
expect($foldable->fold())->toEqualCollapsingWhitespace(join('', [
170170
'<?php $__blaze->pushData([\'name\' => \'Mr. \'.e($name)]); $__env->pushConsumableComponentData([\'name\' => \'Mr. \'.e($name)]); ?>',

tests/Folder/FolderTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@
210210
test('folds components with no blaze directive if enabled in config', function () {
211211
$input = '<x-foldable.input-no-blaze />';
212212

213-
app(Config::class)->add(fixture_path('components/foldable'), fold: true);
213+
app(Config::class)->add(fixture_path('views/components/foldable'), fold: true);
214214

215215
$node = app(Parser::class)->parse($input)[0];
216216
$folded = app(Folder::class)->fold($node);
@@ -221,7 +221,7 @@
221221
test('folds components with blaze directive even if disabled in config', function () {
222222
$input = '<x-foldable.input />';
223223

224-
app(Config::class)->add(fixture_path('components/foldable'), fold: false);
224+
app(Config::class)->add(fixture_path('views/components/foldable'), fold: false);
225225

226226
$node = app(Parser::class)->parse($input)[0];
227227
$folded = app(Folder::class)->fold($node);

tests/Folder/UnblazeTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
$input = '<x-foldable.input-unblaze name="address" />';
1111

1212
$node = app(Parser::class)->parse($input)[0];
13-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/input-unblaze.blade.php')), app(BladeRenderer::class), app(BladeService::class));
13+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input-unblaze.blade.php')), app(BladeRenderer::class), app(BladeService::class));
1414

1515
expect($foldable->fold())->toEqualCollapsingWhitespace(
1616
sprintf('<input %s >', join('', [
@@ -26,7 +26,7 @@
2626
$input = '<x-foldable.nested-input-unblaze />';
2727

2828
$node = app(Parser::class)->parse($input)[0];
29-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/nested-input-unblaze.blade.php')), app(BladeRenderer::class), app(BladeService::class));
29+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/nested-input-unblaze.blade.php')), app(BladeRenderer::class), app(BladeService::class));
3030

3131
expect($foldable->fold())->toEqualCollapsingWhitespace(
3232
sprintf('<div> <input %s ></div>', join('', [
@@ -42,7 +42,7 @@
4242
$input = '<x-foldable.input-unblaze :name="$field" />';
4343

4444
$node = app(Parser::class)->parse($input)[0];
45-
$foldable = new Foldable($node, new ComponentSource(fixture_path('components/foldable/input-unblaze.blade.php')), app(BladeRenderer::class), app(BladeService::class));
45+
$foldable = new Foldable($node, new ComponentSource(fixture_path('views/components/foldable/input-unblaze.blade.php')), app(BladeRenderer::class), app(BladeService::class));
4646

4747
expect($foldable->fold())->toEqualCollapsingWhitespace(
4848
sprintf('<input %s >', join('', [

tests/Memoizer/MemoizerTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
$node = app(Parser::class)->parse($input)[0];
1414
$memoized = app(Memoizer::class)->memoize($node);
1515

16-
$path = fixture_path('components/memoizable/avatar.blade.php');
16+
$path = fixture_path('views/components/memoizable/avatar.blade.php');
1717
$hash = Utils::hash($path);
1818

1919
expect($memoized->render())->toEqualCollapsingWhitespace(join('', [
@@ -58,7 +58,7 @@
5858
test('memoizes components without blaze directive if enabled in config', function () {
5959
$input = '<x-memoizable.avatar-no-blaze />';
6060

61-
app(Config::class)->add(fixture_path('components/memoizable'), memo: true);
61+
app(Config::class)->add(fixture_path('views/components/memoizable'), memo: true);
6262

6363
$node = app(Parser::class)->parse($input)[0];
6464
$memoized = app(Memoizer::class)->memoize($node);

tests/TestCase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ protected function getEnvironmentSetUp($app)
3030
]);
3131

3232
$app['blade.compiler']->anonymousComponentPath(
33-
__DIR__.'/fixtures/components',
33+
__DIR__.'/fixtures/views/components',
3434
);
3535

3636
// Isolate compiled view paths for parallel testing to prevent
File renamed without changes.

0 commit comments

Comments
 (0)