NewSite   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 68
c 2
b 1
f 0
dl 0
loc 126
rs 10
wmc 14

2 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 12 1
F execute() 0 87 13
1
<?php
2
3
/**
4
 * This file is part of Cecil.
5
 *
6
 * (c) Arnaud Ligny <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Cecil\Command;
15
16
use Cecil\Exception\RuntimeException;
17
use Cecil\Util;
18
use Symfony\Component\Console\Input\InputArgument;
19
use Symfony\Component\Console\Input\InputInterface;
20
use Symfony\Component\Console\Input\InputOption;
21
use Symfony\Component\Console\Output\OutputInterface;
22
use Symfony\Component\Yaml\Yaml;
23
24
/**
25
 * NewSite command.
26
 *
27
 * This command creates a new website in the specified directory or the current directory if no path is provided.
28
 * It prompts the user for various details about the website, such as title, baseline, base URL, description, and author information.
29
 * It can also add demo content if the `--demo` option is provided.
30
 * If the `--force` option is used, it will override an existing website in the specified directory.
31
 */
32
class NewSite extends AbstractCommand
33
{
34
    /**
35
     * {@inheritdoc}
36
     */
37
    protected function configure()
38
    {
39
        $this
40
            ->setName('new:site')
41
            ->setDescription('Creates a new website')
42
            ->setDefinition([
43
                new InputArgument('path', InputArgument::OPTIONAL, 'Use the given path as working directory'),
44
                new InputOption('force', 'f', InputOption::VALUE_NONE, 'Override directory if it already exists'),
45
                new InputOption('demo', null, InputOption::VALUE_NONE, 'Add demo content (pages, templates and assets)'),
46
            ])
47
            ->setHelp(
48
                <<<'EOF'
49
The <info>%command.name%</> command creates a new website in the current directory, or in <comment><path></> if provided.
50
If you run this command without any options, it will ask you for the website title, baseline, base URL, description, etc.
51
52
  <info>%command.full_name%</>
53
  <info>%command.full_name% path/to/the/working/directory</>
54
55
To create a new website with <comment>demo content</comment>, run:
56
57
  <info>%command.full_name% --demo</>
58
59
To <comment>override</comment> an existing website, run:
60
61
  <info>%command.full_name% --force</>
62
EOF
63
            );
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     *
69
     * @throws RuntimeException
70
     */
71
    protected function execute(InputInterface $input, OutputInterface $output)
72
    {
73
        $force = $input->getOption('force');
74
        $demo = $input->getOption('demo');
75
76
        try {
77
            // ask to override existing site?
78
            if (Util\File::getFS()->exists(Util::joinFile($this->getPath(false), $this->locateConfigFile($this->getPath())['name'] ?: self::CONFIG_FILE[0])) && !$force) {
79
                $output->writeln('<comment>Website already exists.</comment>');
80
                if (!$this->io->confirm('Do you want to override it?', false)) {
81
                    return 0;
82
                }
83
            }
84
            // define root path
85
            $root = Util\Platform::isPhar() ? Util\Platform::getPharPath() . '/' : realpath(Util::joinFile(__DIR__, '/../../'));
86
            // setup questions
87
            $title = $this->io->ask('Give a title to your website', 'New website');
88
            $baseline = $this->io->ask('Give a baseline to your website', '');
89
            $baseurl = $this->io->ask('Base URL?', '/', [$this, 'validateUrl']);
90
            $description = $this->io->ask('Write a full description of your site', 'Website created with Cecil.');
91
            $demo = ($demo !== false) ?: $this->io->confirm('Add demo content?', false);
92
            // override skeleton default config
93
            $config = Yaml::parseFile(Util::joinPath($root, 'resources/skeleton', self::CONFIG_FILE[0]), Yaml::PARSE_DATETIME);
94
            $config = array_replace_recursive($config, [
95
                'title'       => $title,
96
                'baseline'    => $baseline,
97
                'baseurl'     => $baseurl,
98
                'description' => $description
99
            ]);
100
            $configYaml = Yaml::dump($config, 2, 2);
101
            Util\File::getFS()->dumpFile(Util::joinPath($this->getPath(), $this->locateConfigFile($this->getPath())['name'] ?: self::CONFIG_FILE[0]), $configYaml);
102
            // create path dir
103
            Util\File::getFS()->mkdir($this->getPath(false));
104
            // creates sub dir
105
            foreach (
106
                [
107
                    (string) $this->getBuilder()->getConfig()->get('assets.dir'),
108
                    (string) $this->getBuilder()->getConfig()->get('layouts.dir'),
109
                    (string) $this->getBuilder()->getConfig()->get('pages.dir'),
110
                    (string) $this->getBuilder()->getConfig()->get('static.dir'),
111
                ] as $value
112
            ) {
113
                Util\File::getFS()->mkdir(Util::joinPath($this->getPath(), $value));
114
            }
115
            // copy files
116
            foreach (
117
                [
118
                    'assets/favicon.png',
119
                    'assets/icon.png',
120
                    'pages/index.md',
121
                ] as $value
122
            ) {
123
                Util\File::getFS()->copy(
124
                    Util::joinPath($root, 'resources/skeleton', $value),
125
                    Util::joinPath($this->getPath(), $value)
126
                );
127
            }
128
            // demo: copy all files
129
            if ($demo) {
130
                foreach (
131
                    [
132
                        (string) $this->getBuilder()->getConfig()->get('assets.dir'),
133
                        (string) $this->getBuilder()->getConfig()->get('layouts.dir'),
134
                        (string) $this->getBuilder()->getConfig()->get('pages.dir'),
135
                        (string) $this->getBuilder()->getConfig()->get('static.dir'),
136
                    ] as $value
137
                ) {
138
                    Util\File::getFS()->mirror(
139
                        Util::joinPath($root, 'resources/skeleton', $value),
140
                        Util::joinPath($this->getPath(), $value)
141
                    );
142
                }
143
            }
144
            // done
145
            $output->writeln(\sprintf('<info>Your new website is created in %s.</info>', realpath($this->getPath())));
146
            $this->io->newLine();
147
            $this->io->listing([
148
                'Start the built-in preview server with <info>' . $this->binName() . ' serve</info>',
149
                'You can create a new page with <info>' . $this->binName() . ' new:page</info>',
150
            ]);
151
152
            $this->io->text('Visit <href=https://cecil.app>https://cecil.app</> for documentation and more.');
153
        } catch (\Exception $e) {
154
            throw new RuntimeException(\sprintf($e->getMessage()));
155
        }
156
157
        return 0;
158
    }
159
}
160