StaticSiteCommand::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 12
nc 1
nop 11
dl 0
loc 25
rs 9.8666
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php declare(strict_types=1);
2
3
namespace Cocotte\Command;
4
5
use Cocotte\Console\AbstractCommand;
6
use Cocotte\Console\DocumentedCommand;
7
use Cocotte\Console\Style;
8
use Cocotte\DigitalOcean\ApiToken;
9
use Cocotte\DigitalOcean\ApiTokenOptionProvider;
10
use Cocotte\DigitalOcean\NetworkingConfigurator;
11
use Cocotte\Environment\LazyEnvironment;
12
use Cocotte\Help\DefaultExamples;
13
use Cocotte\Host\HostMount;
14
use Cocotte\Host\HostMountRequired;
15
use Cocotte\Machine\MachineIp;
16
use Cocotte\Machine\MachineName;
17
use Cocotte\Machine\MachineNameOptionProvider;
18
use Cocotte\Machine\MachineRequired;
19
use Cocotte\Machine\MachineState;
20
use Cocotte\Machine\MachineStoragePath;
21
use Cocotte\Shell\ProcessRunner;
22
use Cocotte\Template\StaticSite\StaticSiteCreator;
23
use Cocotte\Template\StaticSite\StaticSiteDeploymentValidator;
24
use Cocotte\Template\StaticSite\StaticSiteHostname;
25
use Cocotte\Template\StaticSite\StaticSiteHostnameOptionProvider;
26
use Cocotte\Template\StaticSite\StaticSiteNamespace;
27
use Cocotte\Template\StaticSite\StaticSiteNamespaceOptionProvider;
28
use Symfony\Component\Console\Input\InputInterface;
29
use Symfony\Component\Console\Input\InputOption;
30
use Symfony\Component\Console\Output\OutputInterface;
31
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
32
use Symfony\Component\Process\Process;
33
34
final class StaticSiteCommand extends AbstractCommand implements
35
    LazyEnvironment,
36
    HostMountRequired,
37
    DocumentedCommand,
38
    MachineRequired
39
{
40
    /**
41
     * @var StaticSiteCreator
42
     */
43
    private $staticSiteCreator;
44
45
    /**
46
     * @var NetworkingConfigurator
47
     */
48
    private $networkingConfigurator;
49
50
    /**
51
     * @var StaticSiteHostname
52
     */
53
    private $staticSiteHostname;
54
55
    /**
56
     * @var Style
57
     */
58
    private $style;
59
60
    /**
61
     * @var ProcessRunner
62
     */
63
    private $processRunner;
64
65
    /**
66
     * @var EventDispatcherInterface
67
     */
68
    private $eventDispatcher;
69
70
    /**
71
     * @var MachineState
72
     */
73
    private $machineState;
74
    /**
75
     * @var StaticSiteNamespace
76
     */
77
    private $staticSiteNamespace;
78
    /**
79
     * @var HostMount
80
     */
81
    private $hostMount;
82
    /**
83
     * @var StaticSiteDeploymentValidator
84
     */
85
    private $staticSiteDeploymentValidator;
86
    /**
87
     * @var MachineIp
88
     */
89
    private $machineIp;
90
91
    public function __construct(
92
        StaticSiteCreator $staticSiteCreator,
93
        NetworkingConfigurator $networkingConfigurator,
94
        StaticSiteHostname $staticSiteHostname,
95
        Style $style,
96
        ProcessRunner $processRunner,
97
        EventDispatcherInterface $eventDispatcher,
98
        MachineState $machineState,
99
        StaticSiteNamespace $staticSiteNamespace,
100
        HostMount $hostMount,
101
        StaticSiteDeploymentValidator $staticSiteDeploymentValidator,
102
        MachineIp $machineIp
103
    ) {
104
        $this->staticSiteCreator = $staticSiteCreator;
105
        $this->networkingConfigurator = $networkingConfigurator;
106
        $this->staticSiteHostname = $staticSiteHostname;
107
        $this->style = $style;
108
        $this->processRunner = $processRunner;
109
        $this->eventDispatcher = $eventDispatcher;
110
        $this->machineState = $machineState;
111
        $this->staticSiteNamespace = $staticSiteNamespace;
112
        $this->hostMount = $hostMount;
113
        $this->staticSiteDeploymentValidator = $staticSiteDeploymentValidator;
114
        parent::__construct();
115
        $this->machineIp = $machineIp;
116
    }
117
118
    public function lazyEnvironmentValues(): array
119
    {
120
        return [
121
            ApiToken::class,
122
            MachineName::class,
123
            MachineStoragePath::class,
124
            StaticSiteNamespace::class,
125
            StaticSiteHostname::class,
126
        ];
127
    }
128
129
    public function optionProviders(): array
130
    {
131
        return [
132
            StaticSiteNamespaceOptionProvider::class,
133
            StaticSiteHostnameOptionProvider::class,
134
            ApiTokenOptionProvider::class,
135
            MachineNameOptionProvider::class,
136
        ];
137
    }
138
139
    protected function eventDispatcher(): EventDispatcherInterface
140
    {
141
        return $this->eventDispatcher;
142
    }
143
144
    protected function doConfigure(): void
145
    {
146
        $this->setName('static-site')
147
            ->addOption(
148
                'skip-networking',
149
                null,
150
                InputOption::VALUE_NONE,
151
                'Do not configure networking. Cannot be true if skip-deploy is true.')
152
            ->addOption(
153
                'skip-deploy',
154
                null,
155
                InputOption::VALUE_NONE,
156
                'Do not deploy to prod after creation.')
157
            ->setDescription($description = 'Create a static website and deploy it to your Docker Machine.')
158
            ->setHelp(
159
                $this->formatHelp($description,
160
                    (new DefaultExamples)->staticSite(),
161
                    (new DefaultExamples)->staticSiteInteractive()
162
                )
163
            );
164
    }
165
166
    protected function doExecute(InputInterface $input, OutputInterface $output)
167
    {
168
        $this->confirm();
169
        $this->assertValidOptions($input);
170
        $this->createSite();
171
        $this->configureNetworking($input);
172
        $this->deploy($input);
173
    }
174
175
    private function sitePath(): string
176
    {
177
        return "{$this->hostMount->sourcePath()}/{$this->staticSiteNamespace}";
178
    }
179
180
    private function confirm(): void
181
    {
182
        if (!$this->style->confirm($this->confirmMessage())) {
183
            throw new \Exception('Cancelled');
184
        };
185
    }
186
187
    private function confirmMessage(): string
188
    {
189
        return "You are about to create a static website in ".
190
            "'<options=bold>{$this->sitePath()}</>'\n".
191
            " and deploy it to Digital Ocean at ".
192
            "'<options=bold>{$this->staticSiteHostname->toString()}</>'.";
193
    }
194
195
    private function completeMessage(): array
196
    {
197
        return [
198
            "Static site successfully deployed at ".
199
            "<options=bold>https://{$this->staticSiteHostname->toString()}</>",
200
        ];
201
    }
202
203
    private function assertValidOptions(InputInterface $input): void
204
    {
205
        if ($input->getOption('skip-networking') && !$input->getOption('skip-deploy')) {
206
            throw new \Exception("Cannot skip networking when deploying");
207
        }
208
    }
209
210
    private function createSite(): void
211
    {
212
        $this->style->writeln("Creating a new static site in {$this->sitePath()}");
213
        $this->staticSiteCreator->create();
214
    }
215
216
    private function configureNetworking(InputInterface $input): void
217
    {
218
        if (!($input->getOption('skip-networking'))) {
219
            $this->style->writeln("Configuring networking for {$this->staticSiteHostname}");
220
            $this->networkingConfigurator->configure(
221
                $this->staticSiteHostname->toHostnameCollection(),
222
                $this->machineIp->toIP()
223
            );
224
        }
225
    }
226
227
    private function deploy(InputInterface $input): void
228
    {
229
        if (!($input->getOption('skip-deploy'))) {
230
            $this->style->writeln('Deploying created site to cloud machine');
231
232
            $this->processRunner->mustRun(
233
                Process::fromShellCommandline('./bin/prod 2>/dev/stdout',
234
                    $this->staticSiteCreator->hostAppPath())
235
            );
236
237
            $this->style->writeln('Waiting for site to respond');
238
239
            $this->staticSiteDeploymentValidator->validate();
240
241
            $this->processRunner->mustRun(Process::fromShellCommandline('./bin/logs -t', $this->staticSiteCreator->hostAppPath()));
242
243
            $this->style->complete($this->completeMessage());
244
        } else {
245
            $this->style->complete("Deployment has been skipped.");
246
        }
247
    }
248
249
}
250