Completed
Pull Request — master (#9)
by ANTHONIUS
02:26
created

InitCommand::initBackupDir()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the dotfiles project.
7
 *
8
 *     (c) Anthonius Munthi <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Dotfiles\Core\Command;
15
16
use Dotfiles\Core\DI\Parameters;
17
use Dotfiles\Core\Exceptions\InvalidOperationException;
18
use Dotfiles\Core\Util\CommandProcessor;
19
use Dotfiles\Core\Util\Toolkit;
20
use Symfony\Component\Console\Input\InputArgument;
21
use Symfony\Component\Console\Input\InputInterface;
22
use Symfony\Component\Console\Input\InputOption;
23
use Symfony\Component\Console\Output\OutputInterface;
24
use Symfony\Component\Console\Question\Question;
25
26
class InitCommand extends Command
27
{
28
    /**
29
     * @var CommandProcessor
30
     */
31
    private $commandProcessor;
32
33
    /**
34
     * @var string
35
     */
36
    private $defaultBackupDir;
37
38
    /**
39
     * @var string
40
     */
41
    private $defaultHomeDir;
42
43
    /**
44
     * @var InputInterface
45
     */
46
    private $input;
47
48
    /**
49
     * @var OutputInterface
50
     */
51
    private $output;
52
53
    /**
54
     * @var Parameters
55
     */
56
    private $parameters;
57
58
    public function __construct(?string $name = null, CommandProcessor $processor, Parameters $parameters)
59
    {
60
        parent::__construct($name);
61
        $this->commandProcessor = $processor;
62
        $this->parameters = $parameters;
63
        $this->defaultHomeDir = $parameters->get('dotfiles.home_dir');
64
        $this->defaultBackupDir = $parameters->get('dotfiles.backup_dir');
65
    }
66
67
    protected function configure(): void
68
    {
69
        $this
70
            ->setName('init')
71
            ->setDescription('Initialize new Dotfiles project.')
72
            ->addArgument('backup-dir', InputArgument::OPTIONAL, 'Local repository directory')
73
            ->addOption('machine', 'm', InputOption::VALUE_OPTIONAL, 'Machine name')
74
            ->addOption('install-dir', 'i', InputOption::VALUE_OPTIONAL, 'Dotfiles instalaltion directory installation')
75
        ;
76
    }
77
78
    /**
79
     * @param InputInterface  $input
80
     * @param OutputInterface $output
81
     *
82
     * @return int|null|void
83
     */
84
    protected function execute(InputInterface $input, OutputInterface $output)
85
    {
86
        $this->input = $input;
87
        $this->output = $output;
88
89
        if (null === ($backupDir = $input->getArgument('backup-dir'))) {
90
            $backupDir = $this->doBackupRepoDir();
91
        }
92
93
        if (null === ($machine = $input->getOption('machine'))) {
94
            $machine = $this->doAskMachineName();
95
        }
96
97
        if (null === ($installDir = $input->getOption('install-dir'))) {
98
            $installDir = $this->doAskInstallDir();
99
        }
100
101
        $this->initDotfilesProfile($backupDir, $machine, $installDir);
102
    }
103
104
    private function doAskInstallDir()
105
    {
106
        $input = $this->input;
107
        $output = $this->output;
108
        $helper = $this->getHelper('question');
109
        $default = getenv('DOTFILES_HOME_DIR').'/.dotfiles';
110
        $question = new Question(sprintf('Your installation directory (<comment>%s</comment>):', $default), $default);
111
112
        return $helper->ask($input, $output, $question);
113
    }
114
115
    private function doAskMachineName()
116
    {
117
        $input = $this->input;
118
        $output = $this->output;
119
        $helper = $this->getHelper('question');
120
        $default = getenv('DOTFILES_MACHINE_NAME');
121
        $question = new Question(sprintf('Please enter your machine name (<comment>%s</comment>):', $default), $default);
122
123
        return $helper->ask($input, $output, $question);
124
    }
125
126
    private function doBackupRepoDir()
127
    {
128
        $input = $this->input;
129
        $output = $this->output;
130
        $helper = $this->getHelper('question');
131
        $default = getenv('DOTFILES_BACKUP_DIR');
132
        $question = new Question("Please enter local backup dir (<comment>$default</comment>): ", $default);
133
        $question->setValidator(function ($answer) {
134
            if (null === $answer) {
135
                throw new InvalidOperationException('You have to define local backup directory');
136
            }
137
            $parent = dirname($answer);
138
            if (!is_dir($parent) || !is_writable($parent)) {
139
                throw new InvalidOperationException(
140
                    "Can not find parent directory, please ensure that $parent is exists and writable"
141
                );
142
            }
143
144
            return $answer;
145
        });
146
147
        $question->setMaxAttempts(3);
148
149
        return $helper->ask($input, $output, $question);
150
    }
151
152
    private function initDotfilesProfile(string $backupDir, string $machine, $installDir): void
153
    {
154
        $time = (new \DateTime())->format('Y-m-d H:i:s');
155
        $envFile = getenv('DOTFILES_HOME_DIR').'/.dotfiles_profile';
156
        Toolkit::ensureFileDir($envFile);
157
        $contents = <<<EOF
158
# generated at $time
159
DOTFILES_MACHINE_NAME=$machine
160
DOTFILES_BACKUP_DIR=$backupDir
161
DOTFILES_INSTALL_DIR=$installDir
162
EOF;
163
164
        file_put_contents($envFile, $contents, LOCK_EX);
165
    }
166
}
167