Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[10.x] Adds make:view Artisan command #48330

Merged
merged 6 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
236 changes: 236 additions & 0 deletions src/Illuminate/Foundation/Console/ViewMakeCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
<?php

namespace Illuminate\Foundation\Console;

use Illuminate\Console\Concerns\CreatesMatchingTest;
use Illuminate\Console\GeneratorCommand;
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputOption;

#[AsCommand(name: 'make:view')]
class ViewMakeCommand extends GeneratorCommand
{
use CreatesMatchingTest;

/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a new view';

/**
* The name and signature of the console command.
*
* @var string
*/
protected $name = 'make:view';

/**
* The type of file being generated.
*
* @var string
*/
protected $type = 'View';

/**
* Build the class with the given name.
*
* @param string $name
* @return string
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
protected function buildClass($name)
{
$contents = parent::buildClass($name);

return str_replace(
'{{ quote }}',
Inspiring::quotes()->random(),
$contents,
);
}

/**
* Get the desired view name from the input.
*
* @return string
*/
protected function getNameInput()
{
$name = trim($this->argument('name'));

$name = str_replace(['\\', '.'], '/', $this->argument('name'));

return $name;
}

/**
* Get the console command arguments.
*
* @return array
*/
protected function getOptions()
{
return [
['extension', null, InputOption::VALUE_OPTIONAL, 'The extension of the generated view.', 'blade.php'],
['force', 'f', InputOption::VALUE_NONE, 'Create the view even if the view already exists'],
];
}

/**
* Get the destination view path.
*
* @param string $name
* @return string
*/
protected function getPath($name)
{
return $this->viewPath(
$this->getNameInput().'.'.$this->option('extension'),
);
}

/**
* Get the stub file for the generator.
*
* @return string
*/
protected function getStub()
{
return $this->resolveStubPath(
'/stubs/view.stub',
);
}

/**
* Get the destination test case path.
*
* @return string
*/
protected function getTestPath()
{
return base_path(
Str::of($this->testClassFullyQualifiedName())
->replace('\\', '/')
->replaceFirst('Tests/Feature', 'tests/Feature')
->append('Test.php')
->value()
);
}

/**
* Get the test stub file for the generator.
*
* @return string
*/
protected function getTestStub()
{
$stubName = 'view.'.($this->option('pest') ? 'pest' : 'test').'.stub';

return file_exists($customPath = $this->laravel->basePath("stubs/$stubName"))
? $customPath
: __DIR__.'/stubs/'.$stubName;
}

/**
* Create the matching test case if requested.
*
* @param string $path
*/
protected function handleTestCreation($path): bool
{
if (! $this->option('test') && ! $this->option('pest')) {
return false;
}

$contents = preg_replace(
['/\{{ namespace \}}/', '/\{{ class \}}/', '/\{{ name \}}/'],
[$this->testNamespace(), $this->testClassName(), $this->testViewName()],
File::get($this->getTestStub()),
);

File::ensureDirectoryExists(dirname($this->getTestPath()), 0755, true);

return File::put($this->getTestPath(), $contents);
}

/**
* Resolve the fully-qualified path to the stub.
*
* @param string $stub
* @return string
*/
protected function resolveStubPath($stub)
{
return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
? $customPath
: __DIR__.$stub;
}

/**
* Get the class fully qualified name for the test.
*
* @return string
*/
protected function testClassFullyQualifiedName()
{
$name = Str::of(Str::lower($this->getNameInput()))->replace('.'.$this->option('extension'), '');

$namespacedName = Str::of(
Str::of($name)
->replace('/', ' ')
->explode(' ')
->map(fn ($part) => Str::of($part)->ucfirst())
->implode('\\')
)
->replace(['-', '_'], ' ')
->explode(' ')
->map(fn ($part) => Str::of($part)->ucfirst())
->implode('');

return 'Tests\\Feature\\View\\'.$namespacedName;
}

/**
* Get the class name for the test.
*
* @return string
*/
protected function testClassName()
{
return Str::of($this->testClassFullyQualifiedName())
->afterLast('\\')
->append('Test')
->value();
}

/**
* Get the namespace for the test.
*
* @return string
*/
protected function testNamespace()
{
return Str::of($this->testClassFullyQualifiedName())
->beforeLast('\\')
->value();
}

/**
* Get the view name for the test.
*
* @return string
*/
protected function testViewName()
{
return Str::of($this->getNameInput())
->replace('/', '.')
->lower()
->value();
}
}
9 changes: 9 additions & 0 deletions src/Illuminate/Foundation/Console/stubs/view.pest.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

it('can render', function () {
$contents = $this->view('{{ name }}', [
//
]);

$contents->assertSee('');
});
3 changes: 3 additions & 0 deletions src/Illuminate/Foundation/Console/stubs/view.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
<!-- {{ quote }} -->
</div>
20 changes: 20 additions & 0 deletions src/Illuminate/Foundation/Console/stubs/view.test.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace {{ namespace }};

use Tests\TestCase;

class {{ class }} extends TestCase
{
/**
* A basic view test example.
*/
public function test_it_can_render(): void
{
$contents = $this->view('{{ name }}', [
//
]);

$contents->assertSee('');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
use Illuminate\Foundation\Console\VendorPublishCommand;
use Illuminate\Foundation\Console\ViewCacheCommand;
use Illuminate\Foundation\Console\ViewClearCommand;
use Illuminate\Foundation\Console\ViewMakeCommand;
use Illuminate\Notifications\Console\NotificationTableCommand;
use Illuminate\Queue\Console\BatchesTableCommand;
use Illuminate\Queue\Console\ClearCommand as QueueClearCommand;
Expand Down Expand Up @@ -203,6 +204,7 @@ class ArtisanServiceProvider extends ServiceProvider implements DeferrableProvid
'Serve' => ServeCommand::class,
'StubPublish' => StubPublishCommand::class,
'TestMake' => TestMakeCommand::class,
'ViewMake' => ViewMakeCommand::class,
'VendorPublish' => VendorPublishCommand::class,
];

Expand Down