Skip to content

Commit

Permalink
[11.x] allow custom view path when making components (#52219)
Browse files Browse the repository at this point in the history
* allow custom view path when making components

currently the `component/` view path is hardcoded into the generator command. while definitely a good default, there can be a need for more custom view paths, depending on each application's specific organization.

this change makes it possible to pass a `--path` option to the command, which will override the location of the view file.

* formatting

---------

Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
browner12 and taylorotwell authored Aug 1, 2024
1 parent ea3c9ed commit cac7d24
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 9 deletions.
28 changes: 19 additions & 9 deletions src/Illuminate/Foundation/Console/ComponentMakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public function handle()
protected function writeView()
{
$path = $this->viewPath(
str_replace('.', '/', 'components.'.$this->getView()).'.blade.php'
str_replace('.', '/', $this->getView()).'.blade.php'
);

if (! $this->files->isDirectory(dirname($path))) {
Expand Down Expand Up @@ -104,24 +104,33 @@ protected function buildClass($name)

return str_replace(
['DummyView', '{{ view }}'],
'view(\'components.'.$this->getView().'\')',
'view(\''.$this->getView().'\')',
parent::buildClass($name)
);
}

/**
* Get the view name relative to the components directory.
* Get the view name relative to the view path.
*
* @return string view
*/
protected function getView()
{
$name = str_replace('\\', '/', $this->argument('name'));
$segments = explode('/', str_replace('\\', '/', $this->argument('name')));

return collect(explode('/', $name))
->map(function ($part) {
return Str::kebab($part);
})
$name = array_pop($segments);

$path = is_string($this->option('path'))
? explode('/', trim($this->option('path'), '/'))
: [
'components',
...$segments,
];

$path[] = $name;

return collect($path)
->map(fn ($segment) => Str::kebab($segment))
->implode('.');
}

Expand Down Expand Up @@ -167,9 +176,10 @@ protected function getDefaultNamespace($rootNamespace)
protected function getOptions()
{
return [
['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the component already exists'],
['inline', null, InputOption::VALUE_NONE, 'Create a component that renders an inline view'],
['view', null, InputOption::VALUE_NONE, 'Create an anonymous component with only a view'],
['path', null, InputOption::VALUE_REQUIRED, 'The location where the component view should be created'],
['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the component already exists'],
];
}
}
52 changes: 52 additions & 0 deletions tests/Integration/Generators/ComponentMakeCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ class ComponentMakeCommandTest extends TestCase
'app/View/Components/Foo.php',
'resources/views/components/foo.blade.php',
'tests/Feature/View/Components/FooTest.php',
'resources/views/custom/path/foo.blade.php',
'app/View/Components/Nested/Foo.php',
'resources/views/components/nested/foo.blade.php',
'tests/Feature/View/Components/Nested/FooTest.php',
];

public function testItCanGenerateComponentFile()
Expand Down Expand Up @@ -50,4 +54,52 @@ public function testItCanGenerateComponentFileWithTest()
$this->assertFilenameExists('resources/views/components/foo.blade.php');
$this->assertFilenameExists('tests/Feature/View/Components/FooTest.php');
}

public function testItCanGenerateComponentFileWithCustomPath()
{
$this->artisan('make:component', ['name' => 'Foo', '--path' => 'custom/path'])
->assertExitCode(0);

$this->assertFileContains([
'namespace App\View\Components;',
'use Illuminate\View\Component;',
'class Foo extends Component',
"return view('custom.path.foo');",
], 'app/View/Components/Foo.php');

$this->assertFilenameExists('resources/views/custom/path/foo.blade.php');
$this->assertFilenameNotExists('tests/Feature/View/Components/FooTest.php');
}

public function testItCanGenerateNestedComponentFile()
{
$this->artisan('make:component', ['name' => 'Nested/Foo'])
->assertExitCode(0);

$this->assertFileContains([
'namespace App\View\Components\Nested;',
'use Illuminate\View\Component;',
'class Foo extends Component',
"return view('components.nested.foo');",
], 'app/View/Components/Nested/Foo.php');

$this->assertFilenameExists('resources/views/components/nested/foo.blade.php');
$this->assertFilenameNotExists('tests/Feature/View/Components/Nested/FooTest.php');
}

public function testItCanGenerateNestedComponentFileWithCustomPath()
{
$this->artisan('make:component', ['name' => 'Nested/Foo', '--path' => 'custom/path'])
->assertExitCode(0);

$this->assertFileContains([
'namespace App\View\Components\Nested;',
'use Illuminate\View\Component;',
'class Foo extends Component',
"return view('custom.path.foo');",
], 'app/View/Components/Nested/Foo.php');

$this->assertFilenameExists('resources/views/custom/path/foo.blade.php');
$this->assertFilenameNotExists('tests/Feature/View/Components/Nested/FooTest.php');
}
}

0 comments on commit cac7d24

Please sign in to comment.