Repository navigation
Expand file tree
/
Copy pathCreateProjectCommand.php
More file actions
154 lines (139 loc) · 6.04 KB
/
Copy pathCreateProjectCommand.php
File metadata and controls
154 lines (139 loc) · 6.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
declare(strict_types=1);
namespace SymPress\Cli\Command;
use InvalidArgumentException;
use RuntimeException;
use SymPress\Cli\Catalog\DefaultPackageCatalog;
use SymPress\Cli\Catalog\DefaultProfileCatalog;
use SymPress\Cli\Catalog\DefaultTemplateCatalog;
use SymPress\Cli\Generator\ProjectGenerator;
use SymPress\Cli\IO\ProjectQuestionnaire;
use SymPress\Cli\Util\ProjectNameNormalizer;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Throwable;
#[AsCommand(
name: 'project:create',
description: 'Create a configured SymPress project from a starter template.',
aliases: ['new', 'create'],
)]
final class CreateProjectCommand extends Command
{
private ProjectQuestionnaire $questionnaire;
private ProjectGenerator $generator;
public function __construct(?ProjectQuestionnaire $questionnaire = null, ?ProjectGenerator $generator = null)
{
parent::__construct();
$this->questionnaire = $questionnaire ?: new ProjectQuestionnaire(
new DefaultTemplateCatalog(),
new DefaultProfileCatalog(),
new DefaultPackageCatalog(),
new ProjectNameNormalizer(),
);
$this->generator = $generator ?: new ProjectGenerator();
}
protected function configure(): void
{
$this
->addArgument('directory', InputArgument::OPTIONAL, 'Target project directory.')
->addOption('template', 't', InputOption::VALUE_REQUIRED, 'Template id, for example sympress-starter.')
->addOption(
'type',
null,
InputOption::VALUE_REQUIRED,
'Project type: website, app, microservice or commerce.',
)
->addOption('name', null, InputOption::VALUE_REQUIRED, 'Human-readable project name.')
->addOption('project-slug', null, InputOption::VALUE_REQUIRED, 'DDEV-safe project slug.')
->addOption(
'package-name',
null,
InputOption::VALUE_REQUIRED,
'Composer package name, for example acme/site.',
)
->addOption('admin-user', null, InputOption::VALUE_REQUIRED, 'WordPress admin username.')
->addOption('admin-password', null, InputOption::VALUE_REQUIRED, 'WordPress admin password.')
->addOption('ddev-tld', null, InputOption::VALUE_REQUIRED, 'DDEV project TLD.')
->addOption(
'package',
'p',
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Runtime package to add, optionally vendor/name:constraint.',
)
->addOption(
'dev-package',
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Development package to add, optionally vendor/name:constraint.',
)
->addOption(
'no-suggested-packages',
null,
InputOption::VALUE_NONE,
'Only add packages passed through --package/--dev-package.',
)
->addOption('template-version', null, InputOption::VALUE_REQUIRED, 'Template version constraint.')
->addOption('repository', null, InputOption::VALUE_REQUIRED, 'Template VCS repository URL.')
->addOption(
'manifest',
null,
InputOption::VALUE_REQUIRED,
'Manifest file, URL or GitHub repository to load template metadata from.',
)
->addOption(
'manifest-ref',
null,
InputOption::VALUE_REQUIRED,
'Explicit immutable Git SHA for an independent manifest.'
)
->addOption(
'allow-template-execution',
null,
InputOption::VALUE_NONE,
'Trust the selected repository revision and its setup commands.'
)
->addOption(
'no-remote-manifest',
null,
InputOption::VALUE_NONE,
'Skip automatic manifest discovery in the selected template repository.',
)
->addOption('composer-bin', null, InputOption::VALUE_REQUIRED, 'Composer executable.', 'composer')
->addOption(
'no-setup',
null,
InputOption::VALUE_NONE,
'Create files only and skip the starter setup command.',
)
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Show the plan without creating files.')
->setHelp(<<<'HELP'
The wizard asks the same kind of incremental questions you know from Symfony Maker,
but for a complete project:
<info>sympress new my-site</info>
<info>sympress new my-site --manifest=https://github.com/acme/starter</info>
<info>sympress new customer-api --type=microservice --no-setup</info>
<info>sympress project:create shop --type=commerce --package=wpackagist-plugin/woocommerce</info>
Interactive mode shows examples, explains package suggestions and writes the
selected defaults into composer.json and .env before the starter setup runs.
HELP);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
try {
$configuration = $this->questionnaire->ask($input, $output, getcwd() ?: '.');
return $this->generator->generate($configuration, $io);
} catch (InvalidArgumentException | RuntimeException $exception) {
$io->error($exception->getMessage());
return Command::INVALID;
} catch (Throwable $exception) {
$io->error($exception->getMessage());
return Command::FAILURE;
}
}
}