Completed
Pull Request — develop (#182)
by Tom
04:37
created

CheckTablesCommand::configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 56
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 2 Features 0
Metric Value
c 2
b 2
f 0
dl 0
loc 56
rs 9.7251
cc 1
eloc 25
nc 1
nop 0

How to fix   Long Method   

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
namespace N98\Magento\Command\Database\Maintain;
4
5
use N98\Magento\Command\AbstractMagentoCommand;
6
use Symfony\Component\Console\Input\InputInterface;
7
use Symfony\Component\Console\Input\InputOption;
8
use Symfony\Component\Console\Output\OutputInterface;
9
use N98\Util\Console\Helper\Table\Renderer\RendererFactory;
10
11
class CheckTablesCommand extends AbstractMagentoCommand
12
{
13
    const MESSAGE_CHECK_NOT_SUPPORTED = 'The storage engine for the table doesn\'t support check';
14
    const MESSAGE_REPAIR_NOT_SUPPORTED = 'The storage engine for the table doesn\'t support repair';
15
16
    /**
17
     * @var \Symfony\Component\Console\Input\InputInterface
18
     */
19
    protected $input = null;
20
21
    /**
22
     * @var \Symfony\Component\Console\Output\OutputInterface
23
     */
24
    protected $output = null;
25
26
    /**
27
     * @var \N98\Util\Console\Helper\DatabaseHelper
28
     */
29
    protected $dbHelper = null;
30
31
    /**
32
     * @var bool
33
     */
34
    protected $showProgress = false;
35
36
    /**
37
     * @var array
38
     */
39
    protected $allowedTypes = array(
40
        'QUICK',
41
        'FAST',
42
        'CHANGED',
43
        'MEDIUM',
44
        'EXTENDED',
45
    );
46
47
    protected function configure()
48
    {
49
        $help = <<<'HELP'
50
<comment>TYPE OPTIONS</comment>
51
52
<info>QUICK</info>
53
            Do not scan the rows to check for incorrect links.
54
            Applies to InnoDB and MyISAM tables and views.
55
<info>FAST</info>
56
            Check only tables that have not been closed properly.
57
            Applies only to MyISAM tables and views; ignored for InnoDB.
58
<info>CHANGED</info>
59
            Check only tables that have been changed since the last check or that
60
            have not been closed properly. Applies only to MyISAM tables and views;
61
            ignored for InnoDB.
62
<info>MEDIUM</info>
63
            Scan rows to verify that deleted links are valid.
64
            This also calculates a key checksum for the rows and verifies this with a
65
            calculated checksum for the keys. Applies only to MyISAM tables and views;
66
            ignored for InnoDB.
67
<info>EXTENDED</info>
68
            Do a full key lookup for all keys for each row. This ensures that the table
69
            is 100% consistent, but takes a long time.
70
            Applies only to MyISAM tables and views; ignored for InnoDB.
71
72
<comment>InnoDB</comment>
73
            InnoDB tables will be optimized with the ALTER TABLE ... ENGINE=InnoDB statement.
74
            The options above do not apply to them.
75
HELP;
76
77
        $this
78
            ->setName('db:maintain:check-tables')
79
            ->setDescription('Check database tables')
80
            ->addOption(
81
                'type',
82
                null,
83
                InputOption::VALUE_OPTIONAL,
84
                'Check type (one of QUICK, FAST, MEDIUM, EXTENDED, CHANGED)',
85
                'MEDIUM'
86
            )
87
            ->addOption('repair', null, InputOption::VALUE_NONE, 'Repair tables (only MyISAM)')
88
            ->addOption(
89
                'table',
90
                null,
91
                InputOption::VALUE_OPTIONAL,
92
                'Process only given table (wildcards are supported)'
93
            )
94
            ->addOption(
95
                'format',
96
                null,
97
                InputOption::VALUE_OPTIONAL,
98
                'Output Format. One of [' . implode(',', RendererFactory::getFormats()) . ']'
99
            )
100
            ->setHelp($help);
101
        ;
102
    }
103
104
    /**
105
     * @throws \InvalidArgumentException
106
     *
107
     */
108
    protected function isTypeAllowed()
109
    {
110
        $type = $this->input->getOption('type');
111
        $type = strtoupper($type);
112
        if ($type && !in_array($type, $this->allowedTypes)) {
113
            throw new \InvalidArgumentException('Invalid type was given');
114
        }
115
    }
116
117
    protected function progressAdvance()
118
    {
119
        if ($this->showProgress) {
120
            $this->getHelper('progress')->advance();
121
        }
122
    }
123
124
    /**
125
     * @param \Symfony\Component\Console\Input\InputInterface   $input
126
     * @param \Symfony\Component\Console\Output\OutputInterface $output
127
     *
128
     * @throws \InvalidArgumentException
129
     * @return int|void
130
     */
131
    protected function execute(InputInterface $input, OutputInterface $output)
132
    {
133
        $this->input  = $input;
134
        $this->output = $output;
135
        $this->isTypeAllowed();
136
        $this->detectMagento($output);
137
        $this->dbHelper     = $this->getHelper('database');
138
        $this->showProgress = $input->getOption('format') == null;
139
140
        if ($input->getOption('table')) {
141
            $resolvedTables = array(
142
                $this->dbHelper->resolveTables(
143
                    array('@check'),
144
                    array(
145
                        'check' => array(
146
                            'tables' => $input->getOption('table')
147
                        )
148
                    )
149
                )
150
            );
151
            $tables         = $resolvedTables[0];
152
        } else {
153
            $tables = $this->dbHelper->getTables();
154
        }
155
156
        $allTableStatus = $this->dbHelper->getTablesStatus();
157
158
        $tableOutput = array();
159
        /** @var \Symfony\Component\Console\Helper\ProgressHelper $progress */
160
        $progress = $this->getHelper('progress');
161
        if ($this->showProgress) {
162
            $progress->start($output, count($tables));
163
        }
164
165
        $methods = array(
166
            'InnoDB' => 1,
167
            'MEMORY' => 1,
168
            'MyISAM' => 1,
169
        );
170
171
        foreach ($tables as $tableName) {
172
            if (isset($allTableStatus[$tableName]) && isset($methods[$allTableStatus[$tableName]['Engine']])) {
173
                $m           = '_check' . $allTableStatus[$tableName]['Engine'];
174
                $tableOutput = array_merge($tableOutput, $this->$m($tableName));
175
            } else {
176
                $tableOutput[] = array(
177
                    'table'     => $tableName,
178
                    'operation' => 'not supported',
179
                    'type'      => '',
180
                    'status'    => '',
181
                );
182
            }
183
            $this->progressAdvance();
184
        }
185
186
        if ($this->showProgress) {
187
            $progress->finish();
188
        }
189
190
        $this->getHelper('table')
191
            ->setHeaders(array('Table', 'Operation', 'Type', 'Status'))
192
            ->renderByFormat($this->output, $tableOutput, $this->input->getOption('format'));
193
    }
194
195
    /**
196
     * @param string $tableName
197
     * @param string $engine
198
     *
199
     * @return array
200
     */
201
    protected function _queryAlterTable($tableName, $engine)
202
    {
203
        /** @var \PDO $connection */
204
        $connection   = $this->dbHelper->getConnection($this->output);
205
        $start        = microtime(true);
206
        $affectedRows = $connection->exec(sprintf('ALTER TABLE %s ENGINE=%s', $tableName, $engine));
207
208
        return array(array(
209
            'table'     => $tableName,
210
            'operation' => 'ENGINE ' . $engine,
211
            'type'      => sprintf('%15s rows', (string)$affectedRows),
212
            'status'    => sprintf('%.3f secs', microtime(true) - $start),
213
        )
214
        );
215
    }
216
217
    /**
218
     * @param string $tableName
219
     *
220
     * @return array
221
     */
222
    protected function _checkInnoDB($tableName)
223
    {
224
        return $this->_queryAlterTable($tableName, 'InnoDB');
225
    }
226
227
    /**
228
     * @param string $tableName
229
     *
230
     * @return array
231
     */
232
    protected function _checkMEMORY($tableName)
233
    {
234
        return $this->_queryAlterTable($tableName, 'MEMORY');
235
    }
236
237
    /**
238
     * @param string $tableName
239
     *
240
     * @return array
241
     */
242
    protected function _checkMyISAM($tableName)
243
    {
244
        $table  = array();
245
        $type   = $this->input->getOption('type');
246
        $result = $this->_query(sprintf('CHECK TABLE %s %s', $tableName, $type));
247
        if ($result['Msg_text'] == self::MESSAGE_CHECK_NOT_SUPPORTED) {
248
            return array();
249
        }
250
251
        $table[] = array(
252
            'table'     => $tableName,
253
            'operation' => $result['Op'],
254
            'type'      => $type,
255
            'status'    => $result['Msg_text'],
256
        );
257
258
        if ($result['Msg_text'] != 'OK'
259
            && $this->input->getOption('repair')
260
        ) {
261
            $result = $this->_query(sprintf('REPAIR TABLE %s %s', $tableName, $type));
262
            if ($result['Msg_text'] != self::MESSAGE_REPAIR_NOT_SUPPORTED) {
263
                $table[] = array(
264
                    'table'     => $tableName,
265
                    'operation' => $result['Op'],
266
                    'type'      => $type,
267
                    'status'    => $result['Msg_text'],
268
                );
269
            }
270
        }
271
        return $table;
272
    }
273
274
    /**
275
     * @param string $sql
276
     *
277
     * @return array|bool
278
     */
279
    protected function _query($sql)
280
    {
281
        /** @var \PDO $connection */
282
        $connection = $this->dbHelper->getConnection($this->output);
283
        $query      = $connection->prepare($sql);
284
        $query->execute();
285
        $result = $query->fetch(\PDO::FETCH_ASSOC);
286
        return $result;
287
    }
288
}
289