Completed
Push — master ( 50e0e2...b82482 )
by Rougin
02:35
created

CreateMigrationCommand::defineColumns()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 15
cts 15
cp 1
rs 7.551
c 0
b 0
f 0
cc 7
eloc 12
nc 6
nop 3
crap 7
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
        $config = $this->filesystem->read('application/config/migration.php');
61
62 27
        $name = underscore($input->getArgument('name'));
63 27
        $path = APPPATH . 'migrations';
64
65 27
        file_exists($path) || mkdir($path);
66
67 27
        $fileName     = date('YmdHis') . '_' . $name;
68 27
        $isSequential = $input->getOption('sequential');
69
70
        // Returns the migration type to be used
71 27
        preg_match('/\$config\[\'migration_type\'\] = \'(.*?)\';/i', $config, $match);
72
73 27
        $fileName = $this->setSequential($match[1], $isSequential, $fileName);
74 27
        $keywords = [ '', '', '', '' ];
75 27
        $keywords = array_replace($keywords, explode('_', $name));
76
77 27
        $data = $this->prepareData($input, $keywords);
78 24
        $data = $this->defineColumns($input, $keywords, $data);
79
80 24
        $rendered = $this->renderer->render('Migration.twig', $data);
81
82 24
        $this->filesystem->write('application/migrations/' . $fileName . '.php', $rendered);
83
84 24
        return $output->writeln('<info>"' . $fileName . '" has been created.</info>');
85
    }
86
87
    /**
88
     * Defines the columns to be included in the migration.
89
     *
90
     * @param  \Symfony\Component\Console\Input\InputInterface $input
91
     * @param  array                                           $keywords
92
     * @param  array                                           $data
93
     * @return array
94
     */
95 24
    protected function defineColumns(InputInterface $input, array $keywords, array $data)
96
    {
97 24
        $data['columns']  = [];
98 24
        $data['defaults'] = [];
99
100 24
        if ($data['command_name'] == 'create' && $input->getOption('from-database') === true) {
101 3
            $data['columns'] = $this->describe->getTable($data['table_name']);
102 24
        } elseif ($data['command_name'] != 'create') {
103 6
            $data['table_name'] = $keywords[3];
104
105 6
            array_push($data['columns'], $this->setColumn($input, $keywords[1]));
106 6
        }
107
108 24
        if ($data['command_name'] == 'modify') {
109 3
            foreach ($this->describe->getTable($data['table_name']) as $column) {
110 3
                $column->getField() != $keywords[1] || array_push($data['defaults'], $column);
111 3
            }
112 3
        }
113
114 24
        return $data;
115
    }
116
117
    /**
118
     * Prepares the data to be inserted in the template.
119
     *
120
     * @param  \Symfony\Component\Console\Input\InputInterface $input
121
     * @param  array                                           $keywords
122
     * @return array
123
     */
124 27
    protected function prepareData(InputInterface $input, array $keywords)
125
    {
126 27
        if ($input->getOption('from-database') && $keywords[0] != 'create') {
127 3
            $message = '--from-database is only available to create_*table*_table keyword';
128
129 3
            throw new \InvalidArgumentException($message);
130
        }
131
132 24
        $data = [];
133
134 24
        $data['command_name'] = $keywords[0];
135 24
        $data['data_types']   = [ 'string' => 'VARCHAR', 'integer' => 'INT' ];
136 24
        $data['class_name']   = underscore($input->getArgument('name'));
137 24
        $data['table_name']   = $keywords[1];
138
139 24
        return $data;
140
    }
141
142
    /**
143
     * Sets properties for a specified column
144
     *
145
     * @param  \Symfony\Component\Console\Input\InputInterface $input
146
     * @param  string                                          $fieldName
147
     * @return \Rougin\Describe\Column
148
     */
149 6
    protected function setColumn(InputInterface $input, $fieldName)
150
    {
151 6
        $column = new \Rougin\Describe\Column;
152
153 6
        $column->setField($fieldName);
154 6
        $column->setNull($input->getOption('null'));
155 6
        $column->setDataType($input->getOption('type'));
156 6
        $column->setLength($input->getOption('length'));
157 6
        $column->setPrimary($input->getOption('primary'));
158 6
        $column->setUnsigned($input->getOption('unsigned'));
159 6
        $column->setDefaultValue($input->getOption('default'));
160 6
        $column->setAutoIncrement($input->getOption('auto_increment'));
161
162 6
        return $column;
163
    }
164
165
    /**
166
     * Changes the file name to sequential mode.
167
     *
168
     * @param  string  $migrationType
169
     * @param  boolean $isSequential
170
     * @param  string  $fileName
171
     * @return string
172
     */
173 27
    protected function setSequential($migrationType, $isSequential = false, $fileName)
174
    {
175 27
        $path = APPPATH . 'migrations';
176
177 27
        if ($migrationType == 'sequential' || $isSequential) {
178 27
            $number = 1;
179
180 27
            $files = new \FilesystemIterator($path, \FilesystemIterator::SKIP_DOTS);
181
182 27
            $number += iterator_count($files);
183
184 27
            $sequence = sprintf('%03d', $number);
185 27
            $fileName = $sequence . '_' . substr($fileName, 15);
186 27
        }
187
188 27
        return $fileName;
189
    }
190
}
191