Passed
Push — master ( 8e2d0f...1c6462 )
by Arnaud
13:42 queued 07:12
created

NewPage::findModel()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 23
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 17
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 23
rs 9.7
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Cecil.
7
 *
8
 * Copyright (c) Arnaud Ligny <[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 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\InputDefinition;
20
use Symfony\Component\Console\Input\InputInterface;
21
use Symfony\Component\Console\Input\InputOption;
22
use Symfony\Component\Console\Output\OutputInterface;
23
24
/**
25
 * Creates a new page.
26
 */
27
class NewPage extends AbstractCommand
28
{
29
    /**
30
     * {@inheritdoc}
31
     */
32
    protected function configure()
33
    {
34
        $this
35
            ->setName('new:page')
36
            ->setDescription('Creates a new page')
37
            ->setDefinition(
38
                new InputDefinition([
39
                    new InputArgument('path', InputArgument::OPTIONAL, 'Use the given path as working directory'),
40
                    new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Page path name'),
41
                    new InputOption('prefix', 'p', InputOption::VALUE_NONE, 'Prefix the file name with the current date (`YYYY-MM-DD`)'),
42
                    new InputOption('force', 'f', InputOption::VALUE_NONE, 'Override the file if already exist'),
43
                    new InputOption('open', 'o', InputOption::VALUE_NONE, 'Open editor automatically'),
44
                    new InputOption('editor', null, InputOption::VALUE_REQUIRED, 'Editor to use with open option'),
45
                ])
46
            )
47
            ->setHelp('Creates a new page file (with filename as title)');
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     *
53
     * @throws RuntimeException
54
     */
55
    protected function execute(InputInterface $input, OutputInterface $output)
56
    {
57
        $name = (string) $input->getOption('name');
58
        $prefix = $input->getOption('prefix');
59
        $force = $input->getOption('force');
60
        $open = $input->getOption('open');
61
        $editor = $input->getOption('editor');
62
63
        try {
64
            // ask
65
            if (empty($name)) {
66
                $name = $this->io->ask('What is the name of the page file?', 'new-page.md');
67
                $prefix = $this->io->confirm('Add date prefix to the filename?', false);
68
                $open = $this->io->confirm('Do you want open the created file with your editor?', false);
69
                if ($open && !$this->getBuilder()->getConfig()->has('editor')) {
70
                    $editor = $this->io->ask('Which editor?');
71
                }
72
            }
73
            // parse given path name
74
            $nameParts = pathinfo($name);
75
            $dirname = trim($nameParts['dirname'], '.');
76
            $basename = $nameParts['basename'];
77
            $extension = $nameParts['extension'];
78
            $title = substr($basename, 0, -\strlen(".$extension"));
79
            $filename = $basename;
80
            if (!\in_array($extension, (array) $this->getBuilder()->getConfig()->get('pages.ext'))) {
81
                $title = $filename;
82
                $filename = "$basename.md"; // force a valid extension
83
            }
84
            $title = ucfirst(str_replace('-', ' ', $title));
85
            $date = date('Y-m-d');
86
            // date prefix?
87
            $datePrefix = $prefix ? sprintf('%s-', $date) : '';
88
            // define target path
89
            $fileRelativePath = sprintf(
90
                '%s%s%s%s%s',
91
                (string) $this->getBuilder()->getConfig()->get('pages.dir'),
92
                DIRECTORY_SEPARATOR,
93
                empty($dirname) ? '' : $dirname . DIRECTORY_SEPARATOR,
94
                $datePrefix,
95
                $filename
96
            );
97
            $filePath = Util::joinFile($this->getPath(), $fileRelativePath);
98
            // ask to override existing file?
99
            if (Util\File::getFS()->exists($filePath) && !$force) {
100
                $output->writeln(sprintf('<comment>The file "%s" already exists.</comment>', $fileRelativePath));
101
                if (!$this->io->confirm('Do you want to override it?', false)) {
102
                    return 0;
103
                }
104
            }
105
            // creates a new file
106
            $model = $this->findModel(sprintf('%s%s', empty($dirname) ? '' : $dirname . DIRECTORY_SEPARATOR, $filename));
107
            $fileContent = str_replace(
108
                ['%title%', '%date%'],
109
                [$title, $date],
110
                $model['content']
111
            );
112
            Util\File::getFS()->dumpFile($filePath, $fileContent);
113
            $output->writeln(sprintf('<info>File "%s" created (with model "%s").</info>', $fileRelativePath, $model['name']));
114
            // open editor?
115
            if ($open) {
116
                if ($editor === null) {
117
                    if (!$this->getBuilder()->getConfig()->has('editor')) {
118
                        $output->writeln('<comment>No editor configured.</comment>');
119
120
                        return 0;
121
                    }
122
                    $editor = (string) $this->getBuilder()->getConfig()->get('editor');
123
                }
124
                $output->writeln(sprintf('<info>Opening file with %s...</info>', ucfirst($editor)));
125
                $this->openEditor($filePath, $editor);
126
            }
127
        } catch (\Exception $e) {
128
            throw new RuntimeException(sprintf($e->getMessage()));
129
        }
130
131
        return 0;
132
    }
133
134
    /**
135
     * Finds the page model and returns its [name, content].
136
     */
137
    private function findModel(string $name): array
138
    {
139
        $name = strstr($name, DIRECTORY_SEPARATOR, true) ?: 'default';
140
        if (file_exists($model = Util::joinFile($this->getPath(), 'models', "$name.md"))) {
141
            return [
142
                'name'    => $name,
143
                'content' => Util\File::fileGetContents($model),
144
            ];
145
        }
146
147
        $content = <<<'EOT'
148
---
149
title: "%title%"
150
date: %date%
151
published: true
152
---
153
_Your content here_
154
155
EOT;
156
157
        return [
158
            'name'    => 'cecil',
159
            'content' => $content,
160
        ];
161
    }
162
}
163