• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Cecilapp / Cecil / 5046041481

pending completion
5046041481

Pull #1697

github

GitHub
Merge 2cd309b47 into a16355c73
Pull Request #1697: perf: native_function_invocation

322 of 322 new or added lines in 62 files covered. (100.0%)

2784 of 4121 relevant lines covered (67.56%)

0.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Command/AbstractCommand.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of Cecil.
7
 *
8
 * Copyright (c) Arnaud Ligny <arnaud@ligny.fr>
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 Cecil\Command;
15

16
use Cecil\Builder;
17
use Cecil\Exception\RuntimeException;
18
use Cecil\Logger\ConsoleLogger;
19
use Cecil\Util;
20
use Symfony\Component\Console\Command\Command;
21
use Symfony\Component\Console\Input\InputInterface;
22
use Symfony\Component\Console\Output\OutputInterface;
23
use Symfony\Component\Console\Style\SymfonyStyle;
24
use Symfony\Component\Process\Process;
25
use Symfony\Component\Yaml\Exception\ParseException;
26
use Symfony\Component\Yaml\Yaml;
27

28
class AbstractCommand extends Command
29
{
30
    public const CONFIG_FILE = 'config.yml';
31
    public const TMP_DIR = '.cecil';
32

33
    /** @var InputInterface */
34
    protected $input;
35

36
    /** @var OutputInterface */
37
    protected $output;
38

39
    /** @var SymfonyStyle */
40
    protected $io;
41

42
    /** @var string */
43
    private $path;
44

45
    /** @var array */
46
    private $configFiles;
47

48
    /** @var array */
49
    private $config;
50

51
    /** @var Builder */
52
    private $builder;
53

54
    /**
55
     * {@inheritdoc}
56
     */
57
    protected function initialize(InputInterface $input, OutputInterface $output)
58
    {
59
        $this->input = $input;
×
60
        $this->output = $output;
×
61
        $this->io = new SymfonyStyle($input, $output);
×
62

63
        if (!\in_array($this->getName(), ['self-update'])) {
×
64
            // working directory
65
            $this->path = getcwd();
×
66
            if ($input->getArgument('path') !== null) {
×
67
                $this->path = (string) $input->getArgument('path');
×
68
            }
69
            if (realpath($this->getPath()) === false) {
×
70
                Util\File::getFS()->mkdir($this->getPath());
×
71
            }
72
            $this->path = realpath($this->getPath());
×
73
            // config file(s)
74
            if (!\in_array($this->getName(), ['new:site'])) {
×
75
                // default
76
                $this->configFiles[self::CONFIG_FILE] = realpath(Util::joinFile($this->getPath(), self::CONFIG_FILE));
×
77
                // from --config=<file>
78
                if ($input->hasOption('config') && $input->getOption('config') !== null) {
×
79
                    foreach (explode(',', (string) $input->getOption('config')) as $configFile) {
×
80
                        $this->configFiles[$configFile] = realpath($configFile);
×
81
                        if (!Util\File::getFS()->isAbsolutePath($configFile)) {
×
82
                            $this->configFiles[$configFile] = realpath(Util::joinFile($this->getPath(), $configFile));
×
83
                        }
84
                    }
85
                }
86
                // checks file(s)
87
                foreach ($this->configFiles as $fileName => $filePath) {
×
88
                    if ($filePath === false || !file_exists($filePath)) {
×
89
                        unset($this->configFiles[$fileName]);
×
90
                        $this->getBuilder()->getLogger()->error(sprintf('Could not find configuration file "%s".', $fileName));
×
91
                    }
92
                }
93
            }
94
        }
95

96
        parent::initialize($input, $output);
×
97
    }
98

99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function run(InputInterface $input, OutputInterface $output)
103
    {
104
        // disable debug mode if a verbosity level is specified
105
        if ($output->getVerbosity() != OutputInterface::VERBOSITY_NORMAL) {
×
106
            putenv('CECIL_DEBUG=false');
×
107
        }
108
        // force verbosity level to "debug" in debug mode
109
        if (getenv('CECIL_DEBUG') == 'true') {
×
110
            $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
×
111
        }
112
        if ($output->isDebug()) {
×
113
            // set env. variable in debug mode
114
            putenv('CECIL_DEBUG=true');
×
115

116
            return parent::run($input, $output);
×
117
        }
118
        // simplified error message
119
        try {
120
            return parent::run($input, $output);
×
121
        } catch (\Exception $e) {
×
122
            if ($this->io === null) {
×
123
                $this->io = new SymfonyStyle($input, $output);
×
124
            }
125
            $this->io->error($e->getMessage());
×
126

127
            exit(1);
×
128
        }
129
    }
130

131
    /**
132
     * Returns the working directory.
133
     */
134
    protected function getPath(): ?string
135
    {
136
        return $this->path;
×
137
    }
138

139
    /**
140
     * Returns config file(s) path.
141
     */
142
    protected function getConfigFiles(): array
143
    {
144
        return array_unique((array) $this->configFiles);
×
145
    }
146

147
    /**
148
     * Creates or returns a Builder instance.
149
     *
150
     * @throws RuntimeException
151
     */
152
    protected function getBuilder(array $config = []): Builder
153
    {
154
        try {
155
            // config
156
            if ($this->config === null) {
×
157
                $siteConfig = [];
×
158
                foreach ($this->getConfigFiles() as $fileName => $filePath) {
×
159
                    if ($filePath === false || false === $configContent = Util\File::fileGetContents($filePath)) {
×
160
                        throw new RuntimeException(sprintf('Can\'t read configuration file "%s".', $fileName));
×
161
                    }
162
                    $siteConfig = array_replace_recursive($siteConfig, Yaml::parse($configContent));
×
163
                }
164
                $this->config = array_replace_recursive($siteConfig, $config);
×
165
            }
166
            // builder
167
            if ($this->builder === null) {
×
168
                $this->builder = (new Builder($this->config, new ConsoleLogger($this->output)))
×
169
                    ->setSourceDir($this->getPath())
×
170
                    ->setDestinationDir($this->getPath());
×
171
            }
172
        } catch (ParseException $e) {
×
173
            throw new RuntimeException(sprintf('Configuration parsing error: %s', $e->getMessage()));
×
174
        } catch (\Exception $e) {
×
175
            throw new RuntimeException($e->getMessage());
×
176
        }
177

178
        return $this->builder;
×
179
    }
180

181
    /**
182
     * Opens path with editor.
183
     *
184
     * @throws RuntimeException
185
     */
186
    protected function openEditor(string $path, string $editor): void
187
    {
188
        $command = sprintf('%s "%s"', $editor, $path);
×
189
        switch (Util\Plateform::getOS()) {
×
190
            case Util\Plateform::OS_WIN:
191
                $command = sprintf('start /B "" %s "%s"', $editor, $path);
×
192
                break;
×
193
            case Util\Plateform::OS_OSX:
194
                // Typora on macOS
195
                if ($editor == 'typora') {
×
196
                    $command = sprintf('open -a typora "%s"', $path);
×
197
                }
198
                break;
×
199
        }
200
        $process = Process::fromShellCommandline($command);
×
201
        $process->run();
×
202
        if (!$process->isSuccessful()) {
×
203
            throw new RuntimeException(sprintf('Can\'t use "%s" editor.', $editor));
×
204
        }
205
    }
206
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc