Skip to content

Commit

Permalink
CLI-1396: [app:new:local] Add project template option (#1838)
Browse files Browse the repository at this point in the history
* CLI-1396: [app:new:local] Add project template option

* kill mutant

* kill mutant
  • Loading branch information
danepowell authored Dec 12, 2024
1 parent 94fa98e commit 2232593
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 10 deletions.
41 changes: 32 additions & 9 deletions src/Command/App/NewCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,42 @@
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\Filesystem\Path;

#[AsCommand(name: 'app:new:local', description: 'Create a new Drupal or Next.js project', aliases: ['new'])]
final class NewCommand extends CommandBase
{
/**
* @var string[]
*/
private static array $distros = [
'acquia_drupal_recommended' => 'acquia/drupal-recommended-project',
'acquia_next_acms' => 'acquia/next-acms',
];
protected function configure(): void
{
$this
->addArgument('directory', InputArgument::OPTIONAL, 'The destination directory');
->addArgument('directory', InputArgument::OPTIONAL, 'The destination directory')
->addOption('template', 't', InputOption::VALUE_OPTIONAL, 'The project template', null, array_keys(self::$distros))
->addUsage('-t acquia_drupal_recommended');
}

/**
* @throws \Acquia\Cli\Exception\AcquiaCliException
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->output->writeln('Acquia recommends most customers use <options=bold>acquia/drupal-recommended-project</> to setup a Drupal project, which includes useful utilities such as Acquia Connector.');
$this->output->writeln('<options=bold>acquia/next-acms</> is a starter template for building a headless site powered by Acquia CMS and Next.js.');
$distros = [
'acquia_drupal_recommended' => 'acquia/drupal-recommended-project',
'acquia_next_acms' => 'acquia/next-acms',
];
$project = $this->io->choice('Choose a starting project', array_values($distros), $distros['acquia_drupal_recommended']);
$project = array_search($project, $distros, true);

if ($input->hasOption('template') && $input->getOption('template')) {
$project = $input->getOption('template');
} else {
$project = $this->io->choice('Choose a starting project', array_values(self::$distros), self::$distros['acquia_drupal_recommended']);
$project = array_search($project, self::$distros, true);
}

if ($input->hasArgument('directory') && $input->getArgument('directory')) {
$dir = Path::canonicalize($input->getArgument('directory'));
Expand All @@ -46,13 +60,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$output->writeln('<info>Creating project. This may take a few minutes.</info>');

if ($project === 'acquia_next_acms') {
$successMessage = "<info>New Next JS project created in $dir. 🎉</info>";
$successMessage = "<info>New Next.js project created in $dir. 🎉</info>";
$this->localMachineHelper->checkRequiredBinariesExist(['node']);
$this->createNextJsProject($dir);
} else {
$successMessage = "<info>New 💧 Drupal project created in $dir. 🎉</info>";
$this->localMachineHelper->checkRequiredBinariesExist(['composer']);
$this->createDrupalProject($distros[$project], $dir);
$this->createDrupalProject(self::$distros[$project], $dir);
}

$this->initializeGitRepository($dir);
Expand All @@ -63,6 +77,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return Command::SUCCESS;
}

/**
* @throws \Acquia\Cli\Exception\AcquiaCliException
*/
private function createNextJsProject(string $dir): void
{
$process = $this->localMachineHelper->execute([
Expand All @@ -77,6 +94,9 @@ private function createNextJsProject(string $dir): void
}
}

/**
* @throws \Acquia\Cli\Exception\AcquiaCliException
*/
private function createDrupalProject(string $project, string $dir): void
{
$process = $this->localMachineHelper->execute([
Expand All @@ -91,6 +111,9 @@ private function createDrupalProject(string $project, string $dir): void
}
}

/**
* @throws \Acquia\Cli\Exception\AcquiaCliException
*/
private function initializeGitRepository(string $dir): void
{
if (
Expand Down
35 changes: 34 additions & 1 deletion tests/phpunit/src/Commands/App/NewCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,40 @@ public function testNewNextJSAppCommand(array $package, string $directory = 'nex
$this->assertStringContainsString('Choose a starting project', $output);
$this->assertStringContainsString($project, $output);
$this->assertTrue($mockFileSystem->isAbsolutePath($this->newProjectDir), 'Directory path is not absolute');
$this->assertStringContainsString('New Next JS project created in ' . $this->newProjectDir, $output);
$this->assertStringContainsString('New Next.js project created in ' . $this->newProjectDir, $output);
}

public function testProjectTemplateOption(): void
{
$this->newProjectDir = Path::makeAbsolute('nextjs', $this->projectDir);

$process = $this->prophet->prophesize(Process::class);
$process->isSuccessful()->willReturn(true);
$process->getExitCode()->willReturn(0);

$localMachineHelper = $this->mockLocalMachineHelper();

$mockFileSystem = $this->mockGetFilesystem($localMachineHelper);

$localMachineHelper->checkRequiredBinariesExist(["node"])
->shouldBeCalled();
$this->mockExecuteNpxCreate($this->newProjectDir, $localMachineHelper, $process);
$localMachineHelper->checkRequiredBinariesExist(["git"])
->shouldBeCalled();
$this->mockExecuteGitInit($localMachineHelper, $this->newProjectDir, $process);
$this->mockExecuteGitAdd($localMachineHelper, $this->newProjectDir, $process);
$this->mockExecuteGitCommit($localMachineHelper, $this->newProjectDir, $process);

$this->executeCommand([
'--template' => 'acquia_next_acms',
'directory' => 'nextjs',
]);

$output = $this->getDisplay();
$this->assertStringContainsString('Acquia recommends most customers use acquia/drupal-recommended-project to setup a Drupal project', $output);
$this->assertStringContainsString('acquia/next-acms', $output);
$this->assertTrue($mockFileSystem->isAbsolutePath($this->newProjectDir), 'Directory path is not absolute');
$this->assertStringContainsString('New Next.js project created in ' . $this->newProjectDir, $output);
}

protected function mockExecuteComposerCreate(
Expand Down

0 comments on commit 2232593

Please sign in to comment.