Passed
Pull Request — master (#1)
by ANTHONIUS
02:46
created

AddCommand::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 3
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\Config\Config;
17
use Dotfiles\Core\Exceptions\InvalidOperationException;
18
use Dotfiles\Core\Util\Filesystem;
19
use Dotfiles\Core\Util\Toolkit;
20
use Psr\Log\LoggerInterface;
21
use Symfony\Component\Console\Input\InputArgument;
22
use Symfony\Component\Console\Input\InputInterface;
23
use Symfony\Component\Console\Input\InputOption;
24
use Symfony\Component\Console\Output\OutputInterface;
25
use Symfony\Component\Finder\Finder;
26
27
class AddCommand extends Command implements CommandInterface
28
{
29
    /**
30
     * @var Config
31
     */
32
    private $config;
33
34
    /**
35
     * @var LoggerInterface
36
     */
37
    private $logger;
38
    /**
39
     * @var OutputInterface
40
     */
41
    private $output;
42
43
    public function __construct(
44
        ?string $name = null,
45
        Config $config,
46
        LoggerInterface $logger
47
    ) {
48
        parent::__construct($name);
49
        $this->config = $config;
50
        $this->logger = $logger;
51
    }
52
53
    protected function configure(): void
54
    {
55
        $this
56
            ->setName('add')
57
            ->setDescription('Add new file into dotfiles manager')
58
            ->addArgument('path', InputArgument::REQUIRED, 'A file or directory name to add. This file must be exists in $HOME directory')
59
            ->addOption('machine', '-m', InputOption::VALUE_OPTIONAL, 'Add this file/directory into machine registry', 'default')
60
            ->addOption('recursive', '-r', InputOption::VALUE_NONE, 'Import all directory contents recursively')
61
        ;
62
    }
63
64
    /**
65
     * @param InputInterface  $input
66
     * @param OutputInterface $output
67
     *
68
     * @return int|null|void
69
     *
70
     * @throws InvalidOperationException when path not exists
71
     */
72
    protected function execute(InputInterface $input, OutputInterface $output)
73
    {
74
        $this->output = $output;
75
        $config = $this->config;
76
        $recursive = $input->getOption('recursive');
77
        $machine = $input->getOption('machine');
78
        $repoDir = $config->get('dotfiles.repo_dir')."/src/$machine/home";
79
        $sourcePath = $input->getArgument('path');
80
        $originPath = $config->get('dotfiles.home_dir').DIRECTORY_SEPARATOR.$sourcePath;
81
        $targetPath = $repoDir.'/'.str_replace('.', '', $sourcePath);
82
83
        if (!is_file($originPath) && !is_dir($originPath)) {
84
            throw new InvalidOperationException("Path <comment>$sourcePath</comment> not exists");
85
        }
86
        Toolkit::ensureDir($repoDir);
87
88
        $basename = basename($sourcePath);
89
        if (0 === strpos($basename, '.')) {
90
            $targetPath = str_replace('.'.$sourcePath, $basename, $targetPath);
91
        }
92
93
        if (is_dir($originPath)) {
94
            $this->doAddDir($originPath, $targetPath, $recursive);
95
        } else {
96
            $this->doAddFile($originPath, $targetPath);
97
        }
98
    }
99
100
    /**
101
     * @param string $origin
102
     * @param string $target
103
     * @param bool   $recursive
104
     *
105
     * @throws InvalidOperationException
106
     */
107
    private function doAddDir(string $origin, string $target, $recursive): void
108
    {
109
        if (!$recursive) {
110
            throw new InvalidOperationException('Add dir without recursive');
111
        }
112
113
        $finder = Finder::create()
114
            ->in($origin)
115
            ->ignoreVCS(true)
116
            ->ignoreDotFiles(false)
117
        ;
118
        $fs = new Filesystem();
119
        $fs->mirror($origin, $target, $finder);
120
        $this->output->writeln(sprintf(
121
            'copy files from <comment>%s</comment> to <comment>%s</comment>',
122
            $origin,
123
            $target
124
        ));
125
    }
126
127
    /**
128
     * @param string $origin
129
     * @param string $target
130
     */
131
    private function doAddFile(string $origin, string $target): void
132
    {
133
        $fs = new Filesystem();
134
        $fs->copy($origin, $target);
135
        $this->output->writeln(
136
            sprintf(
137
                'copy from <comment>%s</comment> to <comment>%s</comment>',
138
                $origin,
139
                $target
140
            )
141
        );
142
    }
143
}
144