Passed
Push — Assets/Image ( bd550f...7a290d )
by Arnaud
09:48 queued 04:01
created

NewPage::execute()   B

Complexity

Conditions 10
Paths 59

Size

Total Lines 61
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 10
eloc 40
nc 59
nop 2
dl 0
loc 61
rs 7.6666
c 2
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Util\Plateform;
14
use Symfony\Component\Console\Input\InputArgument;
15
use Symfony\Component\Console\Input\InputDefinition;
16
use Symfony\Component\Console\Input\InputInterface;
17
use Symfony\Component\Console\Input\InputOption;
18
use Symfony\Component\Console\Output\OutputInterface;
19
use Symfony\Component\Console\Question\ConfirmationQuestion;
20
use Symfony\Component\Process\Process;
21
22
class NewPage extends Command
23
{
24
    /**
25
     * {@inheritdoc}
26
     */
27
    protected function configure()
28
    {
29
        $this
30
            ->setName('new:page')
31
            ->setDescription('Create a new page')
32
            ->setDefinition(
33
                new InputDefinition([
34
                    new InputArgument('name', InputArgument::REQUIRED, 'New page name'),
35
                    new InputArgument('path', InputArgument::OPTIONAL, 'Use the given path as working directory'),
36
                    new InputOption('force', 'f', InputOption::VALUE_NONE, 'Override the file if already exist'),
37
                    new InputOption('open', 'o', InputOption::VALUE_NONE, 'Open editor automatically'),
38
                    new InputOption('prefix', 'p', InputOption::VALUE_NONE, 'Add date (`YYYY-MM-DD`) as a prefix'),
39
                ])
40
            )
41
            ->setHelp('Create a new page file (with a default title and the current date).');
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47
    protected function execute(InputInterface $input, OutputInterface $output)
48
    {
49
        $name = (string) $input->getArgument('name');
50
        $force = $input->getOption('force');
51
        $open = $input->getOption('open');
52
        $prefix = $input->getOption('prefix');
53
54
        try {
55
            $nameParts = pathinfo($name);
56
            $dirname = $nameParts['dirname'];
57
            $filename = $nameParts['filename'];
58
            $date = date('Y-m-d');
59
            $title = $filename;
60
            // date prefix?
61
            $datePrefix = '';
62
            if ($prefix) {
63
                $datePrefix = sprintf('%s-', $date);
64
            }
65
            // path
66
            $fileRelativePath = sprintf(
67
                '%s/%s%s%s.md',
68
                $this->getBuilder($output)->getConfig()->get('content.dir'),
0 ignored issues
show
Bug introduced by
It seems like $this->getBuilder($outpu...g()->get('content.dir') can also be of type array; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

68
                /** @scrutinizer ignore-type */ $this->getBuilder($output)->getConfig()->get('content.dir'),
Loading history...
69
                !$dirname ?: $dirname.'/',
70
                $datePrefix,
71
                $filename
72
            );
73
            $filePath = $this->getPath().'/'.$fileRelativePath;
74
75
            // file already exists?
76
            if ($this->fs->exists($filePath) && !$force) {
77
                $helper = $this->getHelper('question');
78
                $question = new ConfirmationQuestion(
79
                    sprintf('This page already exists. Do you want to override it? [y/n]', $this->getpath()),
80
                    false
81
                );
82
                if (!$helper->ask($input, $output, $question)) {
83
                    return;
84
                }
85
            }
86
87
            // create new file
88
            $fileContent = str_replace(
89
                ['%title%', '%date%'],
90
                [$title, $date],
91
                $this->findModel(sprintf('%s%s', !$dirname ?: $dirname.'/', $filename))
92
            );
93
            $this->fs->dumpFile($filePath, $fileContent);
94
            $output->writeln(sprintf('File "%s" created.', $fileRelativePath));
95
96
            // open editor?
97
            if ($open) {
98
                if (!$this->hasEditor($output)) {
99
                    $output->writeln('<comment>No editor configured.</comment>');
100
                }
101
                $this->openEditor($output, $filePath);
102
            }
103
        } catch (\Exception $e) {
104
            throw new \Exception(sprintf($e->getMessage()));
105
        }
106
107
        return 0;
108
    }
109
110
    /**
111
     * Find the page model and return its content.
112
     *
113
     * @param string $name
114
     *
115
     * @return string
116
     */
117
    protected function findModel(string $name): string
118
    {
119
        $section = strstr($name, '/', true);
120
        if ($section && file_exists($model = sprintf('%s/models/%s.md', $this->getPath(), $section))) {
121
            return file_get_contents($model);
122
        }
123
        if (file_exists($model = sprintf('%s/models/default.md', $this->getPath()))) {
124
            return file_get_contents($model);
125
        }
126
127
        return <<<'EOT'
128
---
129
title: '%title%'
130
date: '%date%'
131
draft: true
132
---
133
134
_[Your content here]_
135
EOT;
136
    }
137
138
    /**
139
     * Editor is configured?
140
     *
141
     * @param OutputInterface $output
142
     *
143
     * @return bool
144
     */
145
    protected function hasEditor(OutputInterface $output): bool
146
    {
147
        return (bool) $this->getBuilder($output)->getConfig()->get('editor');
148
    }
149
150
    /**
151
     * Open new file in editor (if configured).
152
     *
153
     * @param OutputInterface $output
154
     * @param string          $filePath
155
     *
156
     * @return void
157
     */
158
    protected function openEditor(OutputInterface $output, string $filePath)
159
    {
160
        if ($editor = $this->getBuilder($output)->getConfig()->get('editor')) {
161
            $command = sprintf('%s "%s"', $editor, $filePath);
0 ignored issues
show
Bug introduced by
It seems like $editor can also be of type array; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

161
            $command = sprintf('%s "%s"', /** @scrutinizer ignore-type */ $editor, $filePath);
Loading history...
162
            // Typora 4TW!
163
            if ($editor == 'typora') {
164
                if (Plateform::getOS() == Plateform::OS_OSX) {
165
                    $command = sprintf('open -a typora "%s"', $filePath);
166
                }
167
            }
168
            $process = Process::fromShellCommandline($command);
169
            $process->run();
170
            if (!$process->isSuccessful()) {
171
                throw new \Exception(sprintf('Can\'t run "%s".', $command));
172
            }
173
        }
174
    }
175
}
176