Completed
Pull Request — master (#5)
by Rougin
02:12
created

CreateMigrationCommand::setColumn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 11
cts 11
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 11
nc 1
nop 2
crap 1
1
<?php
2
3
namespace Rougin\Refinery\Commands;
4
5
use Symfony\Component\Console\Input\InputOption;
6
use Symfony\Component\Console\Input\InputArgument;
7
use Symfony\Component\Console\Input\InputInterface;
8
use Symfony\Component\Console\Output\OutputInterface;
9
10
/**
11
 * Create Migration Command
12
 *
13
 * Creates a new migration file based on its file name.
14
 *
15
 * @package Refinery
16
 * @author  Rougin Royce Gutib <[email protected]>
17
 */
18
class CreateMigrationCommand extends AbstractCommand
19
{
20
    /**
21
     * Checks whether the command is enabled or not in the current environment.
22
     *
23
     * @return boolean
24
     */
25 3
    public function isEnabled()
26
    {
27 3
        return true;
28
    }
29
30
    /**
31
     * Sets the configurations of the specified command.
32
     *
33
     * @return void
34
     */
35 33
    protected function configure()
36
    {
37 33
        $this->setName('create')
38 33
            ->setDescription('Creates a new migration file')
39 33
            ->addArgument('name', InputArgument::REQUIRED, 'Name of the migration file')
40 33
            ->addOption('from-database', null, InputOption::VALUE_NONE, 'Generates a migration based from the database')
41 33
            ->addOption('sequential', null, InputOption::VALUE_NONE, 'Generates a migration file with a sequential identifier')
42 33
            ->addOption('type', null, InputOption::VALUE_OPTIONAL, 'Data type of the column', 'varchar')
43 33
            ->addOption('length', null, InputOption::VALUE_OPTIONAL, 'Length of the column', 50)
44 33
            ->addOption('auto_increment', null, InputOption::VALUE_OPTIONAL, 'Generates an "AUTO_INCREMENT" flag on the column', false)
45 33
            ->addOption('default', null, InputOption::VALUE_OPTIONAL, 'Generates a default value in the column definition', '')
46 33
            ->addOption('null', null, InputOption::VALUE_OPTIONAL, 'Generates a "NULL" value in the column definition', false)
47 33
            ->addOption('primary', null, InputOption::VALUE_OPTIONAL, 'Generates a "PRIMARY" value in the column definition', false)
48 33
            ->addOption('unsigned', null, InputOption::VALUE_OPTIONAL, 'Generates an "UNSIGNED" value in the column definition', false);
49 33
    }
50
51
    /**
52
     * Executes the command.
53
     *
54
     * @param  \Symfony\Component\Console\Input\InputInterface   $input
55
     * @param  \Symfony\Component\Console\Output\OutputInterface $output
56
     * @return object|\Symfony\Component\Console\Output\OutputInterface
57
     */
58 27
    protected function execute(InputInterface $input, OutputInterface $output)
59
    {
60 27
        $fileName = $this->getFileName($input->getArgument('name'), $input->getOption('sequential'));
61 27
        $keywords = $this->getKeywords($input->getArgument('name'));
62
63 27
        if ($input->getOption('from-database') && $keywords[0] != 'create') {
64 3
            throw new \InvalidArgumentException('--from-database is only available to create_*table*_table keyword');
65
        }
66
67 24
        $data = $this->prepareData($input, $keywords);
68
69 24
        if ($data['command_name'] != 'create') {
70 6
            $data = $this->defineColumns($input, $keywords, $data);
71 6
        }
72
73 24
        $rendered = $this->renderer->render('Migration.twig', $data);
74 24
        $rendered = str_replace("));\n\n\t}", "));\n\t}", $rendered);
75
76 24
        $this->filesystem->write('application/migrations/' . $fileName . '.php', $rendered);
77
78 24
        return $output->writeln('<info>"' . $fileName . '" has been created.</info>');
79
    }
80
81
    /**
82
     * Defines the columns to be included in the migration.
83
     *
84
     * @param  \Symfony\Component\Console\Input\InputInterface $input
85
     * @param  array                                           $keywords
86
     * @param  array                                           $data
87
     * @return array
88
     */
89 6
    protected function defineColumns(InputInterface $input, array $keywords, array $data)
90
    {
91 6
        $data['table_name'] = $keywords[1];
92
93 6
        array_push($data['columns'], $this->setColumn($input, $keywords[2]));
94
95 6
        if ($data['command_name'] == 'modify') {
96 3
            foreach ($this->describe->getTable($data['table_name']) as $column) {
97 3
                $column->getField() != $keywords[2] || array_push($data['defaults'], $column);
98 3
            }
99 3
        }
100
101 6
        return $data;
102
    }
103
104
    /**
105
     * Gets the file name of the specified migration.
106
     *
107
     * @param  string  $name
108
     * @param  boolean $isSequential
109
     * @return string
110
     */
111 27
    protected function getFileName($name, $isSequential = false)
112
    {
113 27
        $migrationType = $this->getMigrationType();
114
115 27
        $fileName = date('YmdHis') . '_' . underscore($name);
116
117 27
        if ($migrationType == 'sequential' || $isSequential) {
118 3
            $number = 1;
119
120 3
            $files = new \FilesystemIterator(APPPATH . 'migrations', \FilesystemIterator::SKIP_DOTS);
121
122 3
            $number += iterator_count($files);
123
124 3
            $sequence = sprintf('%03d', $number);
125 3
            $fileName = $sequence . '_' . substr($fileName, 15);
126 3
        }
127
128 27
        return $fileName;
129
    }
130
131
    /**
132
     * Gets the defined keywords from the command.
133
     *
134
     * @param  string $name
135
     * @return array
136
     */
137 27
    protected function getKeywords($name)
138
    {
139 27
        $empty = [ '', '', '' ];
140 27
        $path  = APPPATH . 'migrations';
141
142 27
        file_exists($path) || mkdir($path);
143
144 27
        preg_match('/(.*?)_(.*?)_table/', underscore($name), $keywords);
145
146 27
        if (strpos($keywords[2], '_in') !== false) {
147 9
            preg_match('/(.*?)_(.*?)_in_(.*?)_table/', underscore($name), $keywords);
148
149 9
            list($keywords[3], $keywords[2]) = [ $keywords[2], $keywords[3] ];
150 9
        }
151
152 27
        array_shift($keywords);
153
154 27
        return array_replace($empty, $keywords);
155
    }
156
157
    /**
158
     * Prepares the data to be inserted in the template.
159
     *
160
     * @param  \Symfony\Component\Console\Input\InputInterface $input
161
     * @param  array                                           $keywords
162
     * @return array
163
     */
164 24
    protected function prepareData(InputInterface $input, array $keywords)
165
    {
166
        $data = [
167 24
            'class_name'   => underscore($input->getArgument('name')),
168 24
            'columns'      => [],
169 24
            'command_name' => $keywords[0],
170 24
            'data_types'   => [ 'string' => 'VARCHAR', 'integer' => 'INT' ],
171 24
            'defaults'     => [],
172 24
            'table_name'   => $keywords[1],
173 24
        ];
174
175 24
        if ($input->getOption('from-database') && $data['command_name'] == 'create') {
176 3
            $data['columns'] = $this->describe->getTable($data['table_name']);
177 3
        }
178
179 24
        return $data;
180
    }
181
182
    /**
183
     * Sets properties for a specified column
184
     *
185
     * @param  \Symfony\Component\Console\Input\InputInterface $input
186
     * @param  string                                          $fieldName
187
     * @return \Rougin\Describe\Column
188
     */
189 6
    protected function setColumn(InputInterface $input, $fieldName)
190
    {
191 6
        $column = new \Rougin\Describe\Column;
192
193 6
        $column->setField($fieldName);
194 6
        $column->setNull($input->getOption('null'));
195 6
        $column->setDataType($input->getOption('type'));
196 6
        $column->setLength($input->getOption('length'));
197 6
        $column->setPrimary($input->getOption('primary'));
198 6
        $column->setUnsigned($input->getOption('unsigned'));
199 6
        $column->setDefaultValue($input->getOption('default'));
200 6
        $column->setAutoIncrement($input->getOption('auto_increment'));
201
202 6
        return $column;
203
    }
204
}
205