Skip to content

Commit c1c9a59

Browse files
committed
[make:*] interactively install dependencies
1 parent cdcd168 commit c1c9a59

File tree

4 files changed

+175
-0
lines changed

4 files changed

+175
-0
lines changed

src/Dependency/DependencyManager.php

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony MakerBundle package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\MakerBundle\Dependency;
13+
14+
use Symfony\Bundle\MakerBundle\ConsoleStyle;
15+
use Symfony\Bundle\MakerBundle\Dependency\Model\OptionalClassDependency;
16+
use Symfony\Bundle\MakerBundle\Dependency\Model\RequiredClassDependency;
17+
use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
18+
use Symfony\Component\Console\Command\Command;
19+
use Symfony\Component\Process\Process;
20+
21+
/**
22+
* @author Jesse Rushlow<[email protected]>
23+
*
24+
* @internal
25+
*/
26+
final class DependencyManager
27+
{
28+
/** @var RequiredClassDependency[] */
29+
private array $requiredClassDependencies = [];
30+
31+
/** @var OptionalClassDependency[] */
32+
private array $optionalClassDependencies = [];
33+
34+
private ConsoleStyle $io;
35+
36+
public function addRequiredDependency(RequiredClassDependency $dependency): self
37+
{
38+
$this->requiredClassDependencies[] = $dependency;
39+
40+
return $this;
41+
}
42+
43+
public function addOptionalDependency(OptionalClassDependency $dependency): self
44+
{
45+
$this->optionalClassDependencies[] = $dependency;
46+
47+
return $this;
48+
}
49+
50+
public function installRequiredDependencies(ConsoleStyle $io, ?string $preInstallMessage): self
51+
{
52+
$this->io = $io;
53+
54+
$preInstallMessage ?: $this->io->caution($preInstallMessage);
55+
56+
foreach ($this->requiredClassDependencies as $dependency) {
57+
if (class_exists($dependency->className) || !$this->askToInstallDependency($dependency)) {
58+
continue;
59+
}
60+
61+
$this->runComposer($dependency);
62+
}
63+
64+
return $this;
65+
}
66+
67+
public function installOptionalDependencies(ConsoleStyle $io, ?string $preInstallMessage): self
68+
{
69+
$this->io = $io;
70+
71+
$preInstallMessage ?: $this->io->caution($preInstallMessage);
72+
73+
foreach ($this->optionalClassDependencies as $dependency) {
74+
if (class_exists($dependency->className) || !$this->askToInstallDependency($dependency)) {
75+
continue;
76+
}
77+
78+
$this->runComposer($dependency);
79+
}
80+
81+
return $this;
82+
}
83+
84+
private function askToInstallDependency(RequiredClassDependency|OptionalClassDependency $dependency): bool
85+
{
86+
return $this->io->confirm(
87+
question: sprintf('Do you want us to run <fg=yellow>composer require %s</> for you?', $dependency->composerPackage),
88+
default: true // @TODO - Should we default to yes or no on this...
89+
);
90+
}
91+
92+
private function runComposer(RequiredClassDependency|OptionalClassDependency $dependency): void
93+
{
94+
$process = Process::fromShellCommandline(
95+
sprintf('composer require%s %s', $dependency->installAsRequireDev ?: ' --dev', $dependency->composerPackage)
96+
);
97+
98+
if (Command::SUCCESS === $process->run()) {
99+
return;
100+
}
101+
102+
$this->io->block($process->getErrorOutput());
103+
104+
throw new RuntimeCommandException(sprintf('Oops! There was a problem installing "%s". You\'ll need to install the package manually.', $dependency->className));
105+
}
106+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony MakerBundle package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\MakerBundle\Dependency\Model;
13+
14+
/**
15+
* @author Jesse Rushlow <[email protected]>
16+
*
17+
* @internal
18+
*/
19+
abstract class AbstractClassDependency
20+
{
21+
public function __construct(
22+
public string $className,
23+
public string $composerPackage,
24+
public bool $installAsRequireDev = false,
25+
) {
26+
}
27+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony MakerBundle package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\MakerBundle\Dependency\Model;
13+
14+
/**
15+
* @author Jesse Rushlow <[email protected]>
16+
*
17+
* @internal
18+
*/
19+
final class OptionalClassDependency extends AbstractClassDependency
20+
{
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony MakerBundle package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\MakerBundle\Dependency\Model;
13+
14+
/**
15+
* @author Jesse Rushlow <[email protected]>
16+
*
17+
* @internal
18+
*/
19+
final class RequiredClassDependency extends AbstractClassDependency
20+
{
21+
}

0 commit comments

Comments
 (0)