• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

orchestral / workbench / 12403824975

19 Dec 2024 12:31AM UTC coverage: 93.849% (+1.2%) from 92.663%
12403824975

push

github

crynobone
Release 8.15.2

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

595 of 634 relevant lines covered (93.85%)

17.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.46
/src/Console/InstallCommand.php
1
<?php
2

3
namespace Orchestra\Workbench\Console;
4

5
use Composer\InstalledVersions;
6
use Illuminate\Console\Command;
7
use Illuminate\Contracts\Console\PromptsForMissingInput;
8
use Illuminate\Filesystem\Filesystem;
9
use Illuminate\Support\Collection;
10
use Orchestra\Testbench\Foundation\Console\Actions\GeneratesFile;
11
use Orchestra\Workbench\Workbench;
12
use Symfony\Component\Console\Attribute\AsCommand;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Input\InputOption;
15
use Symfony\Component\Console\Output\OutputInterface;
16

17
use function Laravel\Prompts\confirm;
18
use function Laravel\Prompts\select;
19
use function Orchestra\Testbench\join_paths;
20
use function Orchestra\Testbench\package_path;
21

22
#[AsCommand(name: 'workbench:install', description: 'Setup Workbench for package development')]
23
class InstallCommand extends Command implements PromptsForMissingInput
24
{
25
    /**
26
     * The `testbench.yaml` default configuration file.
27
     */
28
    public static ?string $configurationBaseFile = null;
29

30
    /**
31
     * Determine if Package also uses Testbench Dusk.
32
     */
33
    protected ?bool $hasTestbenchDusk = null;
34

35
    /** {@inheritDoc} */
36
    #[\Override]
37
    protected function initialize(InputInterface $input, OutputInterface $output)
38
    {
39
        $this->hasTestbenchDusk = InstalledVersions::isInstalled('orchestra/testbench-dusk');
27✔
40

41
        parent::initialize($input, $output);
27✔
42
    }
43

44
    /**
45
     * Execute the console command.
46
     *
47
     * @return int
48
     */
49
    public function handle(Filesystem $filesystem)
50
    {
51
        if (! $this->option('skip-devtool')) {
27✔
52
            $devtool = match (true) {
27✔
53
                \is_bool($this->option('devtool')) => $this->option('devtool'),
27✔
54
                default => $this->components->confirm('Install Workbench DevTool?', true),
×
55
            };
27✔
56

57
            if ($devtool === true) {
27✔
58
                $this->call('workbench:devtool', [
8✔
59
                    '--force' => $this->option('force'),
8✔
60
                    '--no-install' => true,
8✔
61
                    '--basic' => $this->option('basic'),
8✔
62
                ]);
8✔
63
            }
64
        }
65

66
        $workingPath = package_path();
27✔
67

68
        $this->copyTestbenchConfigurationFile($filesystem, $workingPath);
27✔
69
        $this->copyTestbenchDotEnvFile($filesystem, $workingPath);
27✔
70

71
        $this->replaceDefaultLaravelSkeletonInTestbenchConfigurationFile($filesystem, $workingPath);
27✔
72

73
        $this->call('workbench:create-sqlite-db', ['--force' => true]);
27✔
74

75
        return Command::SUCCESS;
27✔
76
    }
77

78
    /**
79
     * Copy the "testbench.yaml" file.
80
     */
81
    protected function copyTestbenchConfigurationFile(Filesystem $filesystem, string $workingPath): void
82
    {
83
        $from = ! \is_null(static::$configurationBaseFile)
27✔
84
            ? (string) realpath(static::$configurationBaseFile)
×
85
            : (string) Workbench::stubFile($this->option('basic') === true ? 'config.basic' : 'config');
27✔
86

87
        $to = join_paths($workingPath, 'testbench.yaml');
27✔
88

89
        (new GeneratesFile(
27✔
90
            filesystem: $filesystem,
27✔
91
            components: $this->components,
27✔
92
            force: (bool) $this->option('force'),
27✔
93
        ))->handle($from, $to);
27✔
94

95
        $workbenchAppNamespacePrefix = rtrim(Workbench::detectNamespace('app') ?? 'Workbench\App\\', '\\');
27✔
96
        $workbenchSeederNamespacePrefix = rtrim(Workbench::detectNamespace('database/seeders') ?? 'Workbench\Database\Seeders\\', '\\');
27✔
97

98
        $serviceProvider = \sprintf('%s\Providers\WorkbenchServiceProvider', $workbenchAppNamespacePrefix);
27✔
99
        $databaseSeeder = \sprintf('%s\DatabaseSeeder', $workbenchSeederNamespacePrefix);
27✔
100

101
        $filesystem->replaceInFile(
27✔
102
            [
27✔
103
                '{{WorkbenchAppNamespace}}',
27✔
104
                '{{ WorkbenchAppNamespace }}',
27✔
105
                '{{WorkbenchSeederNamespace}}',
27✔
106
                '{{ WorkbenchSeederNamespace }}',
27✔
107

108
                '{{WorkbenchServiceProvider}}',
27✔
109
                '{{ WorkbenchServiceProvider }}',
27✔
110
                'Workbench\App\Providers\WorkbenchServiceProvider',
27✔
111

112
                '{{WorkbenchDatabaseSeeder}}',
27✔
113
                '{{ WorkbenchDatabaseSeeder }}',
27✔
114
                'Workbench\Database\Seeders\DatabaseSeeder',
27✔
115
            ],
27✔
116
            [
27✔
117
                $workbenchAppNamespacePrefix,
27✔
118
                $workbenchAppNamespacePrefix,
27✔
119
                $workbenchSeederNamespacePrefix,
27✔
120
                $workbenchSeederNamespacePrefix,
27✔
121

122
                $serviceProvider,
27✔
123
                $serviceProvider,
27✔
124
                $serviceProvider,
27✔
125

126
                $databaseSeeder,
27✔
127
                $databaseSeeder,
27✔
128
                $databaseSeeder,
27✔
129
            ],
27✔
130
            $to
27✔
131
        );
27✔
132
    }
133

134
    /**
135
     * Copy the ".env" file.
136
     */
137
    protected function copyTestbenchDotEnvFile(Filesystem $filesystem, string $workingPath): void
138
    {
139
        $workbenchWorkingPath = join_paths($workingPath, 'workbench');
27✔
140

141
        $from = $this->laravel->basePath('.env.example');
27✔
142

143
        if (! $filesystem->isFile($this->laravel->basePath('.env.example'))) {
27✔
144
            return;
×
145
        }
146

147
        /** @var \Illuminate\Support\Collection<int, string> $choices */
148
        $choices = Collection::make($this->environmentFiles())
27✔
149
            ->reject(static fn ($file) => $filesystem->isFile(join_paths($workbenchWorkingPath, $file)))
27✔
150
            ->values();
27✔
151

152
        if (! $this->option('force') && $choices->isEmpty()) {
27✔
153
            $this->components->twoColumnDetail(
1✔
154
                'File [.env] already exists', '<fg=yellow;options=bold>SKIPPED</>'
1✔
155
            );
1✔
156

157
            return;
1✔
158
        }
159

160
        /** @var string|null $targetEnvironmentFile */
161
        $targetEnvironmentFile = $this->input->isInteractive()
26✔
162
            ? select(
26✔
163
                "Export '.env' file as?",
26✔
164
                $choices->prepend('Skip exporting .env'), // @phpstan-ignore argument.type
26✔
165
            ) : null;
26✔
166

167
        if (\in_array($targetEnvironmentFile, [null, 'Skip exporting .env'])) {
26✔
168
            return;
8✔
169
        }
170

171
        $filesystem->ensureDirectoryExists($workbenchWorkingPath);
18✔
172

173
        $this->generateSeparateEnvironmentFileForTestbenchDusk($filesystem, $workbenchWorkingPath, $targetEnvironmentFile);
18✔
174

175
        (new GeneratesFile(
18✔
176
            filesystem: $filesystem,
18✔
177
            components: $this->components,
18✔
178
            force: (bool) $this->option('force'),
18✔
179
        ))->handle(
18✔
180
            $from,
18✔
181
            join_paths($workbenchWorkingPath, $targetEnvironmentFile)
18✔
182
        );
18✔
183

184
        (new GeneratesFile(
18✔
185
            filesystem: $filesystem,
18✔
186
            force: (bool) $this->option('force'),
18✔
187
        ))->handle(
18✔
188
            (string) Workbench::stubFile('gitignore'),
18✔
189
            join_paths($workbenchWorkingPath, '.gitignore')
18✔
190
        );
18✔
191
    }
192

193
    /**
194
     * Replace the default `laravel` skeleton for Testbench Dusk.
195
     *
196
     * @codeCoverageIgnore
197
     */
198
    protected function replaceDefaultLaravelSkeletonInTestbenchConfigurationFile(Filesystem $filesystem, string $workingPath): void
199
    {
200
        if ($this->hasTestbenchDusk === false) {
201
            return;
202
        }
203

204
        $filesystem->replaceInFile(["laravel: '@testbench'"], ["laravel: '@testbench-dusk'"], join_paths($workingPath, 'testbench.yaml'));
205
    }
206

207
    /**
208
     * Generate separate `.env.dusk` equivalent for Testbench Dusk.
209
     *
210
     * @codeCoverageIgnore
211
     */
212
    protected function generateSeparateEnvironmentFileForTestbenchDusk(Filesystem $filesystem, string $workbenchWorkingPath, string $targetEnvironmentFile): void
213
    {
214
        if ($this->hasTestbenchDusk === false) {
215
            return;
216
        }
217

218
        if ($this->components->confirm('Create separate environment file for Testbench Dusk?', false)) {
219
            (new GeneratesFile(
220
                filesystem: $filesystem,
221
                components: $this->components,
222
                force: (bool) $this->option('force'),
223
            ))->handle(
224
                $this->laravel->basePath('.env.example'),
225
                join_paths($workbenchWorkingPath, str_replace('.env', '.env.dusk', $targetEnvironmentFile))
226
            );
227
        }
228
    }
229

230
    /**
231
     * Get possible environment files.
232
     *
233
     * @return array<int, string>
234
     */
235
    protected function environmentFiles(): array
236
    {
237
        return [
27✔
238
            '.env',
27✔
239
            '.env.example',
27✔
240
            '.env.dist',
27✔
241
        ];
27✔
242
    }
243

244
    /**
245
     * Prompt the user for any missing arguments.
246
     *
247
     * @return void
248
     */
249
    protected function promptForMissingArguments(InputInterface $input, OutputInterface $output)
250
    {
251
        $devtool = null;
26✔
252

253
        if ($input->getOption('skip-devtool') === true) {
26✔
254
            $devtool = false;
×
255
        } elseif (\is_null($input->getOption('devtool'))) {
26✔
256
            $devtool = confirm('Run Workbench DevTool installation?', true);
1✔
257
        }
258

259
        if (! \is_null($devtool)) {
26✔
260
            $input->setOption('devtool', $devtool);
1✔
261
        }
262
    }
263

264
    /**
265
     * Get the console command options.
266
     *
267
     * @return array
268
     */
269
    protected function getOptions()
270
    {
271
        return [
27✔
272
            ['force', 'f', InputOption::VALUE_NONE, 'Overwrite any existing files'],
27✔
273
            ['devtool', null, InputOption::VALUE_NEGATABLE, 'Run DevTool installation'],
27✔
274
            ['basic', null, InputOption::VALUE_NONE, 'Skipped routes and discovers installation'],
27✔
275

276
            /** @deprecated */
277
            ['skip-devtool', null, InputOption::VALUE_NONE, 'Skipped DevTool installation (deprecated)'],
27✔
278
        ];
27✔
279
    }
280
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc