Passed
Push — config ( 8d9d5a )
by Arnaud
05:49
created

AbstractCommand::run()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 10
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 17
rs 9.9332
1
<?php
2
/**
3
 * This file is part of the Cecil/Cecil package.
4
 *
5
 * Copyright (c) Arnaud Ligny <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Cecil\Command;
12
13
use Cecil\Builder;
14
use Cecil\Logger\ConsoleLogger;
15
use Cecil\Util;
16
use Symfony\Component\Console\Command\Command;
17
use Symfony\Component\Console\Input\InputInterface;
18
use Symfony\Component\Console\Output\OutputInterface;
19
use Symfony\Component\Console\Style\SymfonyStyle;
20
use Symfony\Component\Filesystem\Filesystem;
21
use Symfony\Component\Yaml\Exception\ParseException;
22
use Symfony\Component\Yaml\Yaml;
23
24
class AbstractCommand extends Command
25
{
26
    const CONFIG_FILE = 'config.yml';
27
    const TMP_DIR = '.cecil';
28
29
    /** @var InputInterface */
30
    protected $input;
31
32
    /** @var OutputInterface */
33
    protected $output;
34
35
    /** @var SymfonyStyle */
36
    protected $io;
37
38
    /** @var Filesystem */
39
    protected $fs;
40
41
    /** @var string */
42
    protected $path;
43
44
    /** @var array */
45
    protected $configFiles;
46
47
    /** @var Builder */
48
    protected $builder;
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    protected function initialize(InputInterface $input, OutputInterface $output)
54
    {
55
        $this->input = $input;
56
        $this->output = $output;
57
        $this->io = new SymfonyStyle($input, $output);
58
        $this->fs = new Filesystem();
59
60
        if (!in_array($this->getName(), ['self-update'])) {
61
            // working directory
62
            $this->path = getcwd();
63
            if ($input->getArgument('path') !== null) {
64
                $this->path = (string) $input->getArgument('path');
65
            }
66
            if (realpath($this->getPath()) === false) {
67
                $this->fs->mkdir($this->getPath());
68
            }
69
            $this->path = realpath($this->getPath());
70
            // config file(s)
71
            if (!in_array($this->getName(), ['new:site'])) {
72
                // default
73
                $this->configFiles[self::CONFIG_FILE] = realpath(Util::joinFile($this->getPath(), self::CONFIG_FILE));
74
                // from --config=<file>
75
                if ($input->hasOption('config') && $input->getOption('config') !== null) {
76
                    foreach (explode(',', (string) $input->getOption('config')) as $configFile) {
77
                        $this->configFiles[$configFile] = realpath($configFile);
78
                        if (!Util\File::getFS()->isAbsolutePath($configFile)) {
79
                            $this->configFiles[$configFile] = realpath(Util::joinFile($this->getPath(), $configFile));
80
                        }
81
                    }
82
                }
83
                // checks file(s)
84
                foreach ($this->configFiles as $fileName => $filePath) {
85
                    if (!file_exists($filePath)) {
86
                        $this->getBuilder()->getLogger()->error(\sprintf('Could not find configuration file "%s": uses others/default.', $fileName));
87
                        unset($this->configFiles[$fileName]);
88
                    }
89
                }
90
            }
91
        }
92
93
        parent::initialize($input, $output);
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99
    public function run(InputInterface $input, OutputInterface $output)
100
    {
101
        if ($output->isDebug()) {
102
            putenv('CECIL_DEBUG=true');
103
104
            return parent::run($input, $output);
105
        }
106
        // simplified error message
107
        try {
108
            return parent::run($input, $output);
109
        } catch (\Exception $e) {
110
            if ($this->io === null) {
111
                $this->io = new SymfonyStyle($input, $output);
112
            }
113
            $this->io->error($e->getMessage());
114
115
            exit(1);
116
        }
117
    }
118
119
    /**
120
     * Returns the working directory.
121
     */
122
    protected function getPath(): ?string
123
    {
124
        return $this->path;
125
    }
126
127
    /**
128
     * Returns config file(s) path.
129
     */
130
    protected function getConfigFiles(): array
131
    {
132
        return $this->configFiles;
133
    }
134
135
    /**
136
     * Creates or returns a Builder instance.
137
     */
138
    protected function getBuilder(array $config = []): Builder
139
    {
140
        try {
141
            $siteConfig = [];
142
            foreach ($this->getConfigFiles() as $fileName => $filePath) {
143
                if (is_file($filePath)) {
144
                    $configContent = Util\File::fileGetContents($filePath);
145
                    if ($configContent === false) {
146
                        throw new \Exception(\sprintf('Can\'t read configuration file "%s".', $fileName));
147
                    }
148
                    $siteConfig = array_replace_recursive($siteConfig, Yaml::parse($configContent));
149
                }
150
            }
151
            $config = array_replace_recursive($siteConfig, $config);
152
153
            $this->builder = (new Builder($config, new ConsoleLogger($this->output)))
154
                ->setSourceDir($this->getPath())
155
                ->setDestinationDir($this->getPath());
156
        } catch (ParseException $e) {
157
            throw new \Exception(sprintf('Configuration file parse error: %s', $e->getMessage()));
158
        } catch (\Exception $e) {
159
            throw new \Exception($e->getMessage());
160
        }
161
162
        return $this->builder;
163
    }
164
}
165