Completed
Push — develop ( 6f71dd...40edc3 )
by Tom
11s
created

CompareVersionsCommand   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 186
Duplicated Lines 10.22 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 5
Bugs 2 Features 1
Metric Value
wmc 28
c 5
b 2
f 1
lcom 1
cbo 6
dl 19
loc 186
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
B configure() 19 24 1
F execute() 0 119 23
B logJUnit() 0 27 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace N98\Magento\Command\System\Setup;
4
5
use N98\Magento\Command\AbstractMagentoCommand;
6
use N98\JUnitXml\Document as JUnitXmlDocument;
7
use Symfony\Component\Console\Input\InputInterface;
8
use Symfony\Component\Console\Input\InputOption;
9
use Symfony\Component\Console\Output\OutputInterface;
10
use N98\Util\Console\Helper\Table\Renderer\RendererFactory;
11
12
class CompareVersionsCommand extends AbstractMagentoCommand
13
{
14 View Code Duplication
    protected function configure()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
15
    {
16
        $this
17
            ->setName('sys:setup:compare-versions')
18
            ->addOption('ignore-data', null, InputOption::VALUE_NONE, 'Ignore data updates')
19
            ->addOption('log-junit', null, InputOption::VALUE_REQUIRED, 'Log output to a JUnit xml file.')
20
            ->addOption(
21
                'errors-only',
22
                null,
23
                InputOption::VALUE_NONE,
24
                'Only display Setup resources where Status equals Error.'
25
            )
26
            ->addOption(
27
                'format',
28
                null,
29
                InputOption::VALUE_OPTIONAL,
30
                'Output Format. One of [' . implode(',', RendererFactory::getFormats()) . ']'
31
            )
32
            ->setDescription('Compare module version with core_resource table.');
33
        $help = <<<HELP
34
Compares module version with saved setup version in `core_resource` table and displays version mismatch.
35
HELP;
36
        $this->setHelp($help);
37
    }
38
39
    /**
40
     * @param InputInterface  $input
41
     * @param OutputInterface $output
42
     *
43
     * @return int|null|void
44
     */
45
    protected function execute(InputInterface $input, OutputInterface $output)
46
    {
47
        $this->detectMagento($output);
48
        if ($this->initMagento()) {
49
            $time = microtime(true);
50
            $modules            = \Mage::getConfig()->getNode('modules');
51
            $resourceModel      = $this->_getResourceSingleton('core/resource', 'Mage_Core_Model_Resource_Resource');
52
            $setups             = \Mage::getConfig()->getNode('global/resources')->children();
53
            $ignoreDataUpdate   = $input->getOption('ignore-data');
54
55
            $headers = array('Setup', 'Module', 'DB', 'Data', 'Status');
56
            if ($ignoreDataUpdate) {
57
                unset($headers[array_search('Data', $headers)]);
58
            }
59
60
            $hasStatusErrors = false;
61
62
            $errorCounter = 0;
63
            $table = array();
64
            foreach ($setups as $setupName => $setup) {
65
                $moduleName     = (string) $setup->setup->module;
66
                $moduleVersion  = (string) $modules->{$moduleName}->version;
67
                $dbVersion      = (string) $resourceModel->getDbVersion($setupName);
68
                if (!$ignoreDataUpdate) {
69
                    $dataVersion = (string) $resourceModel->getDataVersion($setupName);
70
                }
71
                $ok = $dbVersion == $moduleVersion;
72
                if ($ok && !$ignoreDataUpdate) {
73
                    $ok = $dataVersion == $moduleVersion;
0 ignored issues
show
Bug introduced by
The variable $dataVersion does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
74
                }
75
                if (!$ok) {
76
                    $errorCounter++;
77
                }
78
79
                $row = array(
80
                    'Setup'     => $setupName,
81
                    'Module'    => $moduleVersion,
82
                    'DB'        => $dbVersion,
83
                );
84
85
                if (!$ignoreDataUpdate) {
86
                    $row['Data-Version'] = $dataVersion;
87
                }
88
                $row['Status'] = $ok ? 'OK' : 'Error';
89
90
                if (!$ok) {
91
                    $hasStatusErrors = true;
92
                }
93
94
                $table[] = $row;
95
            }
96
97
            if ($input->getOption('errors-only')) {
98
                $table = array_filter($table, function ($row) {
99
                    return ($row['Status'] === 'Error');
100
                });
101
            }
102
103
            //if there is no output format
104
            //highlight the status
105
            //and show error'd rows at bottom
106
            if (!$input->getOption('format')) {
107
                usort($table, function ($a, $b) {
108
                    if ($a['Status'] !== 'OK' && $b['Status'] === 'OK') {
109
                        return 1;
110
                    }
111
                    if ($a['Status'] === 'OK' && $b['Status'] !== 'OK') {
112
                        return -1;
113
                    }
114
                    return strcmp($a['Setup'], $b['Setup']);
115
                });
116
117
                array_walk($table, function (&$row) {
118
                    $status             = $row['Status'];
119
                    $availableStatus    = array('OK' => 'info', 'Error' => 'error');
120
                    $statusString       = sprintf(
121
                        '<%s>%s</%s>',
122
                        $availableStatus[$status],
123
                        $status,
124
                        $availableStatus[$status]
125
                    );
126
                    $row['Status'] = $statusString;
127
                });
128
            }
129
130
            if ($input->getOption('log-junit')) {
131
                $this->logJUnit($table, $input->getOption('log-junit'), microtime($time) - $time);
132
            } else {
133
                $this->getHelper('table')
134
                    ->setHeaders($headers)
135
                    ->renderByFormat($output, $table, $input->getOption('format'));
136
137
                //if no output format specified - output summary line
138
                if (!$input->getOption('format')) {
139
                    if ($errorCounter > 0) {
140
                        $this->writeSection(
141
                            $output,
142
                            sprintf(
143
                                '%s error%s %s found!',
144
                                $errorCounter,
145
                                $errorCounter === 1 ? '' : 's',
146
                                $errorCounter === 1 ? 'was' : 'were'
147
                            ),
148
                            'error'
149
                        );
150
                    } else {
151
                        $this->writeSection($output, 'No setup problems were found.', 'info');
152
                    }
153
                }
154
            }
155
156
            if ($hasStatusErrors) {
157
                //Return a non-zero status to indicate there is an error in the setup scripts.
158
                return 1;
159
            } else {
160
                return 0;
161
            }
162
        }
163
    }
164
165
    /**
166
     * @param array $data
167
     * @param string $filename
168
     * @param float $duration
169
     */
170
    protected function logJUnit(array $data, $filename, $duration)
171
    {
172
        $document = new JUnitXmlDocument();
173
        $suite = $document->addTestSuite();
174
        $suite->setName('n98-magerun: ' . $this->getName());
175
        $suite->setTimestamp(new \DateTime());
176
        $suite->setTime($duration);
177
178
        $testCase = $suite->addTestCase();
179
        $testCase->setName('Magento Setup Version Test');
180
        $testCase->setClassname('CompareVersionsCommand');
181
        if (count($data) > 0) {
182
            foreach ($data as $moduleSetup) {
183
                if (stristr($moduleSetup['Status'], 'error')) {
184
                    $testCase->addFailure(
185
                        sprintf(
186
                            'Setup Script Error: [Setup %s]',
187
                            $moduleSetup['Setup']
188
                        ),
189
                        'MagentoSetupScriptVersionException'
190
                    );
191
                }
192
            }
193
        }
194
195
        $document->save($filename);
196
    }
197
}
198