master

laravel/framework

Last updated at: 29/12/2023 09:23

ViewMakeCommand.php

TLDR

The src/Illuminate/Foundation/Console/ViewMakeCommand.php file is a part of the Illuminate\Foundation\Console namespace. It contains a class called ViewMakeCommand, which is used to create a new view file. The class extends the GeneratorCommand class and uses the CreatesMatchingTest trait. The file also contains several methods that are used to perform various tasks such as building the class, getting the path for the view, resolving the stub path, handling test creation, and getting the test stub file.

Methods

buildClass

This method is used to build the class with the given name. It calls the parent class's buildClass method and replaces the {{ quote }} placeholder in the generated class contents with a random quote from the Inspiring class.

getPath

This method is used to get the destination view path. It concatenates the given view name with the extension specified as an option.

getNameInput

This method is used to get the desired view name from the input. It trims the argument name, replaces backslashes and dots with slashes, and returns the modified name.

getStub

This method is used to get the stub file for the generator. It resolves the stub path using the resolveStubPath method.

resolveStubPath

This method is used to resolve the fully-qualified path to the stub. It checks if a custom stub path exists and returns it if it does. Otherwise, it returns the default stub path.

getTestPath

This method is used to get the destination test case path. It replaces backslashes with slashes, replaces the 'Tests/Feature' string with 'tests/Feature', appends 'Test.php' to the modified name, and returns the result.

handleTestCreation

This method is used to create the matching test case if requested. It checks if the --test or --pest options are present. If not, it returns false. Otherwise, it reads the contents of the test stub file, replaces placeholders with appropriate values, ensures the directory for the test path exists, and writes the contents to the test file.

testNamespace

This method is used to get the namespace for the test. It extracts the namespace part from the fully-qualified name of the test class.

testClassName

This method is used to get the class name for the test. It extracts the class name part from the fully-qualified name of the test class and appends 'Test' to it.

testClassFullyQualifiedName

This method is used to get the fully-qualified name of the test class. It modifies the input view name by replacing slashes with spaces, capitalizing each part, removing hyphens and underscores, and converting it to an array of words. It then concatenates the words with backslashes, adds the 'Tests\Feature\View' prefix, and returns the result.

getTestStub

This method is used to get the test stub file for the generator. It determines the stub name based on the --pest option and checks if a custom stub path exists. If it does, it returns the custom path. Otherwise, it returns the default stub path.

testViewName

This method is used to get the view name for the test. It replaces slashes with dots, converts the result to lowercase, and returns it.

getOptions

This method is used to get the console command options. It returns an array of options, including the extension option and the force option.

<?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 destination view path.
     *
     * @param  string  $name
     * @return string
     */
    protected function getPath($name)
    {
        return $this->viewPath(
            $this->getNameInput().'.'.$this->option('extension'),
        );
    }

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

    /**
     * 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 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()
        );
    }

    /**
     * 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);
    }

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

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

    /**
     * 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 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;
    }

    /**
     * Get the view name for the test.
     *
     * @return string
     */
    protected function testViewName()
    {
        return Str::of($this->getNameInput())
            ->replace('/', '.')
            ->lower()
            ->value();
    }

    /**
     * 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'],
        ];
    }
}