Completed
Push — master ( 8eb8ec...69233f )
by mark
01:27 queued 01:23
created

Init::resolvePath()   B

Complexity

Conditions 7
Paths 13

Size

Total Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 10.1359

Importance

Changes 0
Metric Value
dl 0
loc 42
ccs 12
cts 20
cp 0.6
rs 8.3146
c 0
b 0
f 0
cc 7
nc 13
nop 2
crap 10.1359
1
<?php
2
3
/**
4
 * MIT License
5
 * For full license information, please view the LICENSE file that was distributed with this source code.
6
 */
7
8
namespace Phinx\Console\Command;
9
10
use InvalidArgumentException;
11
use RuntimeException;
12
use Symfony\Component\Console\Command\Command;
13
use Symfony\Component\Console\Input\InputArgument;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Output\OutputInterface;
16
17
class Init extends Command
18
{
19
    const FILE_NAME = 'phinx';
20
21
    /**
22
     * @var string
23
     */
24
    protected static $defaultName = 'init';
25
26
    /**
27
     * {@inheritDoc}
28
     *
29
     * @return void
30
     */
31
    protected function configure()
32
    {
33
        $this->setDescription('Initialize the application for Phinx')
34
            ->addOption('--format', '-f', InputArgument::OPTIONAL, 'What format should we use to initialize?', 'yml')
35
            ->addArgument('path', InputArgument::OPTIONAL, 'Which path should we initialize for Phinx?')
36
            ->setHelp(sprintf(
37
                '%sInitializes the application for Phinx%s',
38
                PHP_EOL,
39
                PHP_EOL
40
            ));
41 35
    }
42
43 35
    /**
44 35
     * Initializes the application.
45 35
     *
46 35
     * @param \Symfony\Component\Console\Input\InputInterface $input Interface implemented by all input classes.
47 35
     * @param \Symfony\Component\Console\Output\OutputInterface $output Interface implemented by all output classes.
48 35
     *
49
     * @return int 0 on success
50 35
     */
51 35
    protected function execute(InputInterface $input, OutputInterface $output)
52
    {
53
        $format = strtolower($input->getOption('format'));
54
        $path = $this->resolvePath($input, $format);
55
        $this->writeConfig($path, $format);
56
57
        $output->writeln("<info>created</info> {$path}");
58
59
        return AbstractCommand::CODE_SUCCESS;
60
    }
61
62 2
    /**
63
     * Return valid $path for Phinx's config file.
64
     *
65 2
     * @param \Symfony\Component\Console\Input\InputInterface $input Interface implemented by all input classes.
66
     * @param string $format Format to resolve for
67 2
     *
68
     * @throws \InvalidArgumentException
69
     *
70
     * @return string
71 2
     */
72
    protected function resolvePath(InputInterface $input, $format)
73 2
    {
74
        // get the migration path from the config
75
        $path = (string)$input->getArgument('path');
76
77
        if (!in_array($format, ['yaml', 'yml', 'json', 'php'])) {
78
            throw new InvalidArgumentException(sprintf(
79
                'Invalid format "%s". Format must be either yaml, yml, json, or php.',
80
                $format
81 2
            ));
82 2
        }
83
84 2
        // Fallback
85 1
        if (!$path) {
86 1
            $path = getcwd() . DIRECTORY_SEPARATOR . self::FILE_NAME . '.' . $format;
87
        }
88 1
89
        // Adding file name if necessary
90
        if (is_dir($path)) {
91
            $path .= DIRECTORY_SEPARATOR . self::FILE_NAME . '.' . $format;
92 1
        }
93
94
        // Check if path is available
95 1
        $dirname = dirname($path);
96
        if (is_dir($dirname) && !is_file($path)) {
97
            return $path;
98 1
        }
99
100
        // Path is valid, but file already exists
101
        if (is_file($path)) {
102
            throw new InvalidArgumentException(sprintf(
103
                'Config file "%s" already exists.',
104
                $path
105 1
            ));
106 1
        }
107
108
        // Dir is invalid
109
        throw new InvalidArgumentException(sprintf(
110
            'Invalid path "%s" for config file.',
111
            $path
112
        ));
113
    }
114
115
    /**
116
     * Writes Phinx's config in provided $path
117
     *
118
     * @param string $path Config file's path.
119
     * @param string $format Format to use for config file
120
     *
121
     * @throws \InvalidArgumentException
122
     * @throws \RuntimeException
123
     *
124
     * @return void
125
     */
126
    protected function writeConfig($path, $format = 'yml')
127
    {
128
        // Check if dir is writable
129
        $dirname = dirname($path);
130
        if (!is_writable($dirname)) {
131
            throw new InvalidArgumentException(sprintf(
132
                'The directory "%s" is not writable',
133
                $dirname
134
            ));
135
        }
136
137
        if ($format === 'yaml') {
138
            $format = 'yml';
139
        }
140
141
        // load the config template
142
        if (is_dir(__DIR__ . '/../../../../data')) {
143
            $contents = file_get_contents(__DIR__ . '/../../../../data/' . self::FILE_NAME . '.' . $format . '.dist');
144
        } else {
145
            throw new RuntimeException(sprintf(
146
                'Could not find template for format "%s".',
147
                $format
148
            ));
149
        }
150
151
        if (file_put_contents($path, $contents) === false) {
152
            throw new RuntimeException(sprintf(
153
                'The file "%s" could not be written to',
154
                $path
155
            ));
156
        }
157
    }
158
}
159