Completed
Push — develop ( 21139f...eaa140 )
by Tom
12s
created

IncrementalCommand   C

Complexity

Total Complexity 62

Size/Duplication

Total Lines 630
Duplicated Lines 9.21 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 62
c 2
b 1
f 0
lcom 1
cbo 2
dl 58
loc 630
rs 5.2795

30 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 11 1
A _runStructureOrDataScripts() 0 16 1
A _listDetailedUpdateInformation() 0 11 1
A execute() 0 19 3
A _loadSecondConfig() 0 6 1
A _getResource() 0 4 1
A _getAvaiableDbFilesFromResource() 16 16 2
A _getAvaiableDataFilesFromResource() 14 14 2
A _setProtectedPropertyFromObjectToValue() 7 7 1
A _getDbVersionFromName() 0 4 1
A _getDbDataVersionFromName() 0 4 1
A _getConfiguredVersionFromResourceObject() 0 6 1
A _log() 0 4 1
A _setOutput() 0 4 1
A _setInput() 0 4 1
A _getTestedVersions() 0 4 1
A _getAllSetupResourceObjects() 0 19 4
A _callProtectedMethodFromObject() 0 8 1
A _getProtectedPropertyFromObject() 7 8 1
B _getAllSetupResourceObjectThatNeedUpdates() 0 20 5
B _outputUpdateInformation() 0 45 4
A _outputFileArray() 0 12 3
D _runNamedSetupResource() 0 65 11
B _processExceptionDuringUpdate() 0 39 2
A _checkCacheSettings() 0 15 2
A _restoreEventContext() 0 5 1
A _stashEventContext() 0 7 1
A _init() 0 19 3
A _analyzeSetupResourceClasses() 0 16 1
B _runAllStructureUpdates() 14 28 3

How to fix   Duplicated Code    Complexity   

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:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like IncrementalCommand often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use IncrementalCommand, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace N98\Magento\Command\System\Setup;
4
5
use Exception;
6
use N98\Magento\Command\AbstractMagentoCommand;
7
use ReflectionClass;
8
use RuntimeException;
9
use Symfony\Component\Console\Input\InputInterface;
10
use Symfony\Component\Console\Input\InputOption;
11
use Symfony\Component\Console\Output\OutputInterface;
12
13
/**
14
 * Class IncrementalCommand
15
 *
16
 * @package N98\Magento\Command\System\Setup
17
 * @codeCoverageIgnore
18
 */
19
class IncrementalCommand extends AbstractMagentoCommand
20
{
21
    const TYPE_MIGRATION_STRUCTURE = 'structure';
22
    const TYPE_MIGRATION_DATA      = 'data';
23
24
    /**
25
     * @var OutputInterface
26
     */
27
    protected $_output;
28
29
    /**
30
     * @var InputInterface
31
     */
32
    protected $_input;
33
34
    /**
35
     * Holds our copy of the global config.
36
     *
37
     * Loaded to avoid grabbing the cached version, and so
38
     * we still have all our original information when we
39
     * destroy the real configuration
40
     *
41
     * @var mixed $_secondConfig
42
     */
43
    protected $_secondConfig;
44
45
    protected $_eventStash;
46
47
    /**
48
     * @var array
49
     */
50
    protected $_config;
51
52
    protected function configure()
53
    {
54
        $this
55
            ->setName('sys:setup:incremental')
56
            ->setDescription('List new setup scripts to run, then runs one script')
57
            ->addOption('stop-on-error', null, InputOption::VALUE_NONE, 'Stops execution of script on error')
58
            ->setHelp(
59
                'Examines an un-cached configuration tree and determines which ' .
60
                'structure and data setup resource scripts need to run, and then runs them.'
61
            );
62
    }
63
64
    /**
65
     * @param InputInterface $input
66
     * @param OutputInterface $output
67
     *
68
     * @return int|null|void
69
     */
70
    protected function execute(InputInterface $input, OutputInterface $output)
71
    {
72
        $this->_config = $this->getCommandConfig();
73
74
        //sets output so we can access it from all methods
75
        $this->_setOutput($output);
76
        $this->_setInput($input);
77
        if (false === $this->_init()) {
78
            return;
79
        }
80
        $needsUpdate = $this->_analyzeSetupResourceClasses();
81
82
        if (count($needsUpdate) == 0) {
83
            return;
84
        }
85
        $this->_listDetailedUpdateInformation($needsUpdate);
86
        $this->_runAllStructureUpdates($needsUpdate);
87
        $output->writeln('We have run all the setup resource scripts.');
88
    }
89
90
    protected function _loadSecondConfig()
91
    {
92
        $config = new \Mage_Core_Model_Config;
93
        $config->loadBase(); //get app/etc
94
        $this->_secondConfig = \Mage::getConfig()->loadModulesConfiguration('config.xml', $config);
95
    }
96
97
    /**
98
     * @return array
99
     */
100
    protected function _getAllSetupResourceObjects()
101
    {
102
        $config = $this->_secondConfig;
103
        $resources = $config->getNode('global/resources')->children();
104
        $setupResources = array();
105
        foreach ($resources as $name => $resource) {
106
            if (!$resource->setup) {
107
                continue;
108
            }
109
            $className = 'Mage_Core_Model_Resource_Setup';
110
            if (isset($resource->setup->class)) {
111
                $className = $resource->setup->getClassName();
112
            }
113
114
            $setupResources[$name] = new $className($name);
115
        }
116
117
        return $setupResources;
118
    }
119
120
    /**
121
     * @return \Mage_Core_Model_Resource
122
     */
123
    protected function _getResource()
124
    {
125
        return \Mage::getResourceSingleton('core/resource');
126
    }
127
128
    /**
129
     * @param \Mage_Core_Model_Resource_Setup $setupResource
130
     * @param array $args
131
     *
132
     * @return array|mixed
133
     */
134 View Code Duplication
    protected function _getAvaiableDbFilesFromResource($setupResource, $args = array())
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...
135
    {
136
        $result = $this->_callProtectedMethodFromObject('_getAvailableDbFiles', $setupResource, $args);
137
138
        //an install runs the install script first, then any upgrades
139
        if ($args[0] == \Mage_Core_Model_Resource_Setup::TYPE_DB_INSTALL) {
140
            $args[0] = \Mage_Core_Model_Resource_Setup::TYPE_DB_UPGRADE;
141
            $args[1] = $result[0]['toVersion'];
142
            $result = array_merge(
143
                $result,
144
                $this->_callProtectedMethodFromObject('_getAvailableDbFiles', $setupResource, $args)
145
            );
146
        }
147
148
        return $result;
149
    }
150
151
    /**
152
     * @param \Mage_Core_Model_Resource_Setup $setupResource
153
     * @param array $args
154
     *
155
     * @return array|mixed
156
     */
157 View Code Duplication
    protected function _getAvaiableDataFilesFromResource($setupResource, $args = array())
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...
158
    {
159
        $result = $this->_callProtectedMethodFromObject('_getAvailableDataFiles', $setupResource, $args);
160
        if ($args[0] == \Mage_Core_Model_Resource_Setup::TYPE_DATA_INSTALL) {
161
            $args[0] = \Mage_Core_Model_Resource_Setup::TYPE_DATA_UPGRADE;
162
            $args[1] = $result[0]['toVersion'];
163
            $result = array_merge(
164
                $result,
165
                $this->_callProtectedMethodFromObject('_getAvailableDbFiles', $setupResource, $args)
166
            );
167
        }
168
169
        return $result;
170
    }
171
172
    /**
173
     * @param string $method
174
     * @param object $object
175
     * @param array $args
176
     *
177
     * @return mixed
178
     */
179
    protected function _callProtectedMethodFromObject($method, $object, $args = array())
180
    {
181
        $r = new ReflectionClass($object);
182
        $m = $r->getMethod($method);
183
        $m->setAccessible(true);
184
185
        return $m->invokeArgs($object, $args);
186
    }
187
188
    /**
189
     * @param string $property
190
     * @param object $object
191
     * @param mixed $value
192
     */
193 View Code Duplication
    protected function _setProtectedPropertyFromObjectToValue($property, $object, $value)
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...
194
    {
195
        $r = new ReflectionClass($object);
196
        $p = $r->getProperty($property);
197
        $p->setAccessible(true);
198
        $p->setValue($object, $value);
199
    }
200
201
    /**
202
     * @param string $property
203
     * @param object $object
204
     *
205
     * @return mixed
206
     */
207 View Code Duplication
    protected function _getProtectedPropertyFromObject($property, $object)
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...
208
    {
209
        $r = new ReflectionClass($object);
210
        $p = $r->getProperty($property);
211
        $p->setAccessible(true);
212
213
        return $p->getValue($object);
214
    }
215
216
    /**
217
     * @param string $name
218
     *
219
     * @return string
220
     */
221
    protected function _getDbVersionFromName($name)
222
    {
223
        return $this->_getResource()->getDbVersion($name);
224
    }
225
226
    /**
227
     * @param string $name
228
     *
229
     * @return string
230
     */
231
    protected function _getDbDataVersionFromName($name)
232
    {
233
        return $this->_getResource()->getDataVersion($name);
234
    }
235
236
    /**
237
     * @param Object $object
238
     *
239
     * @return mixed
240
     */
241
    protected function _getConfiguredVersionFromResourceObject($object)
242
    {
243
        $moduleConfig = $this->_getProtectedPropertyFromObject('_moduleConfig', $object);
244
245
        return $moduleConfig->version;
246
    }
247
248
    /**
249
     * @param bool|array $setupResources
250
     *
251
     * @return array
252
     */
253
    protected function _getAllSetupResourceObjectThatNeedUpdates($setupResources = false)
254
    {
255
        $setupResources = $setupResources ? $setupResources : $this->_getAllSetupResourceObjects();
256
        $needsUpdate = array();
257
        foreach ($setupResources as $name => $setupResource) {
0 ignored issues
show
Bug introduced by
The expression $setupResources of type boolean|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
258
            $db_ver = $this->_getDbVersionFromName($name);
259
            $db_data_ver = $this->_getDbDataVersionFromName($name);
260
            $config_ver = $this->_getConfiguredVersionFromResourceObject($setupResource);
261
262
            if (
263
                (string) $config_ver == (string) $db_ver && //structure
264
                (string) $config_ver == (string) $db_data_ver //data
265
            ) {
266
                continue;
267
            }
268
            $needsUpdate[$name] = $setupResource;
269
        }
270
271
        return $needsUpdate;
272
    }
273
274
    /**
275
     * @param string $message
276
     */
277
    protected function _log($message)
278
    {
279
        $this->_output->writeln($message);
280
    }
281
282
    /**
283
     * @param OutputInterface $output
284
     */
285
    protected function _setOutput(OutputInterface $output)
286
    {
287
        $this->_output = $output;
288
    }
289
290
    /**
291
     * @param InputInterface $input
292
     */
293
    protected function _setInput(InputInterface $input)
294
    {
295
        $this->_input = $input;
296
    }
297
298
    /**
299
     * @param array $needsUpdate
300
     */
301
    protected function _outputUpdateInformation(array $needsUpdate)
302
    {
303
        $output = $this->_output;
304
        foreach ($needsUpdate as $name => $setupResource) {
305
            $dbVersion = $this->_getDbVersionFromName($name);
306
            $dbDataVersion = $this->_getDbDataVersionFromName($name);
307
            $configVersion = $this->_getConfiguredVersionFromResourceObject($setupResource);
308
309
            $moduleConfig = $this->_getProtectedPropertyFromObject('_moduleConfig', $setupResource);
310
            $output->writeln(
311
                array(
312
                    '+--------------------------------------------------+',
313
                    'Resource Name:             ' . $name,
314
                    'For Module:                ' . $moduleConfig->getName(),
315
                    'Class:                     ' . get_class($setupResource),
316
                    'Current Structure Version: ' . $dbVersion,
317
                    'Current Data Version:      ' . $dbDataVersion,
318
                    'Configured Version:        ' . $configVersion,
319
                )
320
            );
321
322
            $args = array(
323
                '',
324
                (string) $dbVersion,
325
                (string) $configVersion,
326
            );
327
328
            $args[0] = $dbVersion
329
                ? \Mage_Core_Model_Resource_Setup::TYPE_DB_UPGRADE
330
                : \Mage_Core_Model_Resource_Setup::TYPE_DB_INSTALL;
331
            $output->writeln('Structure Files to Run: ');
332
            $filesStructure = $this->_getAvaiableDbFilesFromResource($setupResource, $args);
333
            $this->_outputFileArray($filesStructure, $output);
0 ignored issues
show
Unused Code introduced by
The call to IncrementalCommand::_outputFileArray() has too many arguments starting with $output.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
334
            $output->writeln("");
335
336
            $args[0] = $dbVersion
337
                ? \Mage_Core_Model_Resource_Setup::TYPE_DATA_UPGRADE
338
                : \Mage_Core_Model_Resource_Setup::TYPE_DATA_INSTALL;
339
            $output->writeln('Data Files to Run: ');
340
            $filesData = $this->_getAvaiableDataFilesFromResource($setupResource, $args);
341
            $this->_outputFileArray($filesData, $output);
0 ignored issues
show
Unused Code introduced by
The call to IncrementalCommand::_outputFileArray() has too many arguments starting with $output.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
342
            $output->writeln('+--------------------------------------------------+');
343
            $output->writeln('');
344
        }
345
    }
346
347
    /**
348
     * @param array $files
349
     */
350
    protected function _outputFileArray($files)
351
    {
352
        $output = $this->_output;
353
        if (count($files) == 0) {
354
            $output->writeln('No files found');
355
356
            return;
357
        }
358
        foreach ($files as $file) {
359
            $output->writeln(str_replace(\Mage::getBaseDir() . '/', '', $file['fileName']));
360
        }
361
    }
362
363
    /**
364
     * Runs a single named setup resource
365
     *
366
     * This method nukes the global/resources node in the global config
367
     * and then repopulates it with **only** the $name resource. Then it
368
     * calls the standard Magento `applyAllUpdates` method.
369
     *
370
     * The benefit of this approach is we don't need to recreate the entire
371
     * setup resource running logic ourselves.  Yay for code reuse
372
     *
373
     * The downside is we should probably exit quickly, as anything else that
374
     * uses the global/resources node is going to behave weird.
375
     *
376
     * @todo     Repopulate global config after running?  Non trivial since setNode escapes strings
377
     *
378
     * @param string $name
379
     * @param array $needsUpdate
380
     * @param string $type
381
     *
382
     * @throws RuntimeException
383
     * @internal param $string
384
     */
385
    protected function _runNamedSetupResource($name, array $needsUpdate, $type)
386
    {
387
        $output = $this->_output;
388
        if (!in_array($type, array(self::TYPE_MIGRATION_STRUCTURE, self::TYPE_MIGRATION_DATA))) {
389
            throw new RuntimeException('Invalid Type [' . $type . ']: structure, data is valid');
390
        }
391
392
        if (!array_key_Exists($name, $needsUpdate)) {
393
            $output->writeln('<error>No updates to run for ' . $name . ', skipping </error>');
394
395
            return;
396
        }
397
398
        //remove all other setup resources from configuration
399
        //(in memory, do not persist this to cache)
400
        $realConfig = \Mage::getConfig();
401
        $resources = $realConfig->getNode('global/resources');
402
        foreach ($resources->children() as $resource) {
403
            if (!$resource->setup) {
404
                continue;
405
            }
406
            unset($resource->setup);
407
        }
408
        //recreate our specific node in <global><resources></resource></global>
409
        //allows for theoretical multiple runs
410
        $setupResourceConfig = $this->_secondConfig->getNode('global/resources/' . $name);
411
        $moduleName = $setupResourceConfig->setup->module;
412
        $className = $setupResourceConfig->setup->class;
413
414
        $specificResource = $realConfig->getNode('global/resources/' . $name);
415
        $setup = $specificResource->addChild('setup');
416
        if ($moduleName) {
417
            $setup->addChild('module', $moduleName);
418
        } else {
419
            $output->writeln(
420
                '<error>No module node configured for ' . $name . ', possible configuration error </error>'
421
            );
422
        }
423
424
        if ($className) {
425
            $setup->addChild('class', $className);
426
        }
427
428
        //and finally, RUN THE UPDATES
429
        try {
430
            ob_start();
431
            if ($type == self::TYPE_MIGRATION_STRUCTURE) {
432
                $this->_stashEventContext();
433
                \Mage_Core_Model_Resource_Setup::applyAllUpdates();
434
                $this->_restoreEventContext();
435
            } else {
436
                if ($type == self::TYPE_MIGRATION_DATA) {
437
                    \Mage_Core_Model_Resource_Setup::applyAllDataUpdates();
438
                }
439
            }
440
            $exceptionOutput = ob_get_clean();
441
            $this->_output->writeln($exceptionOutput);
442
        } catch (Exception $e) {
443
            $exceptionOutput = ob_get_clean();
444
            $this->_processExceptionDuringUpdate($e, $name, $exceptionOutput);
445
            if ($this->_input->getOption('stop-on-error')) {
446
                throw new RuntimeException('Setup stopped with errors');
447
            }
448
        }
449
    }
450
451
    /**
452
     * @param Exception $e
453
     * @param string $name
454
     * @param string $magentoExceptionOutput
455
     */
456
    protected function _processExceptionDuringUpdate(
457
        Exception $e,
458
        $name,
459
        $magentoExceptionOutput
460
    ) {
461
        $output = $this->_output;
462
        $output->writeln(array(
463
            "<error>Magento encountered an error while running the following setup resource.</error>",
464
            "",
465
            "    $name ",
466
            "",
467
            "<error>The Good News:</error> You know the error happened, and the database",
468
            "information below will  help you fix this error!",
469
            "",
470
            "<error>The Bad News:</error> Because Magento/MySQL can't run setup resources",
471
            "transactionally your database is now in an half upgraded, invalid",
472
            "state. Even if you fix the error, new errors may occur due to",
473
            "this half upgraded, invalid state.",
474
            '',
475
            "What to Do: ",
476
            "1. Figure out why the error happened, and manually fix your",
477
            "   database and/or system so it won't happen again.",
478
            "2. Restore your database from backup.",
479
            "3. Re-run the scripts.",
480
            "",
481
            "Exception Message:",
482
            $e->getMessage(),
483
            "",
484
        ));
485
486
        if ($magentoExceptionOutput) {
487
            $this->getHelper('dialog')->askAndValidate(
488
                $output,
489
                '<question>Press Enter to view raw Magento error text:</question> '
490
            );
491
            $output->writeln("Magento Exception Error Text:");
492
            echo $magentoExceptionOutput, "\n"; //echoing (vs. writeln) to avoid seg fault
493
        }
494
    }
495
496
    /**
497
     * @return bool
498
     */
499
    protected function _checkCacheSettings()
500
    {
501
        $output = $this->_output;
502
        $allTypes = \Mage::app()->useCache();
503
        if ($allTypes['config'] !== '1') {
504
            $output->writeln('<error>ERROR: Config Cache is Disabled</error>');
505
            $output->writeln('This command will not run with the configuration cache disabled.');
506
            $output->writeln('Please change your Magento settings at System -> Cache Management');
507
            $output->writeln('');
508
509
            return false;
510
        }
511
512
        return true;
513
    }
514
515
    /**
516
     * @param string $toUpdate
517
     * @param array $needsUpdate
518
     * @param string $type
519
     */
520
    protected function _runStructureOrDataScripts($toUpdate, array $needsUpdate, $type)
521
    {
522
        $output = $this->_output;
523
        $output->writeln('The next ' . $type . ' update to run is <info>' . $toUpdate . '</info>');
524
        $this->getHelper('dialog')->askAndValidate(
525
            $output,
526
            '<question>Press Enter to Run this update: </question>'
527
        );
528
529
        $start = microtime(true);
530
        $this->_runNamedSetupResource($toUpdate, $needsUpdate, $type);
531
        $time_ran = microtime(true) - $start;
532
        $output->writeln('');
533
        $output->writeln(ucwords($type) . ' update <info>' . $toUpdate . '</info> complete.');
534
        $output->writeln('Ran in ' . floor($time_ran * 1000) . 'ms');
535
    }
536
537
    /**
538
     * @return array
539
     */
540
    protected function _getTestedVersions()
541
    {
542
        return $this->_config['tested-versions'];
543
    }
544
545
    protected function _restoreEventContext()
546
    {
547
        $app = \Mage::app();
548
        $this->_setProtectedPropertyFromObjectToValue('_events', $app, $this->_eventStash);
549
    }
550
551
    protected function _stashEventContext()
552
    {
553
        $app = \Mage::app();
554
        $events = $this->_getProtectedPropertyFromObject('_events', $app);
555
        $this->_eventStash = $events;
556
        $this->_setProtectedPropertyFromObjectToValue('_events', $app, array());
557
    }
558
559
    /**
560
     * @return bool
561
     */
562
    protected function _init()
563
    {
564
        //bootstrap magento
565
        $this->detectMagento($this->_output);
566
        if (!$this->initMagento()) {
567
            return false;
568
        }
569
570
        //don't run if cache is off.  If cache is off that means
571
        //setup resource will run automagically
572
        if (!$this->_checkCacheSettings()) {
573
            return false;
574
        }
575
576
        //load a second, not cached, config.xml tree
577
        $this->_loadSecondConfig();
578
579
        return true;
580
    }
581
582
    /**
583
     * @return array
584
     */
585
    protected function _analyzeSetupResourceClasses()
586
    {
587
        $output = $this->_output;
588
        $this->writeSection($output, 'Analyzing Setup Resource Classes');
589
        $setupResources = $this->_getAllSetupResourceObjects();
590
        $needsUpdate = $this->_getAllSetupResourceObjectThatNeedUpdates($setupResources);
591
592
        $output->writeln(
593
            'Found <info>' . count($setupResources) . '</info> configured setup resource(s)</info>'
594
        );
595
        $output->writeln(
596
            'Found <info>' . count($needsUpdate) . '</info> setup resource(s) which need an update</info>'
597
        );
598
599
        return $needsUpdate;
600
    }
601
602
    /**
603
     * @param array $needsUpdate
604
     */
605
    protected function _listDetailedUpdateInformation(array $needsUpdate)
606
    {
607
        $output = $this->_output;
608
        $this->getHelper('dialog')->askAndValidate(
609
            $output,
610
            '<question>Press Enter to View Update Information: </question>'
611
        );
612
613
        $this->writeSection($output, 'Detailed Update Information');
614
        $this->_outputUpdateInformation($needsUpdate, $output);
0 ignored issues
show
Unused Code introduced by
The call to IncrementalCommand::_outputUpdateInformation() has too many arguments starting with $output.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
615
    }
616
617
    /**
618
     * @param array $needsUpdate
619
     */
620
    protected function _runAllStructureUpdates(array $needsUpdate)
621
    {
622
        $output = $this->_output;
623
        $this->writeSection($output, "Run Structure Updates");
624
        $output->writeln('All structure updates run before data updates.');
625
        $output->writeln('');
626
627
        $c = 1;
628
        $total = count($needsUpdate);
629 View Code Duplication
        foreach ($needsUpdate as $key => $value) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
630
            $toUpdate = $key;
631
            $this->_runStructureOrDataScripts($toUpdate, $needsUpdate, self::TYPE_MIGRATION_STRUCTURE);
632
            $output->writeln("($c of $total)");
633
            $output->writeln('');
634
            $c++;
635
        }
636
637
        $this->writeSection($output, "Run Data Updates");
638
        $c = 1;
639
        $total = count($needsUpdate);
640 View Code Duplication
        foreach ($needsUpdate as $key => $value) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
641
            $toUpdate = $key;
642
            $this->_runStructureOrDataScripts($toUpdate, $needsUpdate, self::TYPE_MIGRATION_DATA);
643
            $output->writeln("($c of $total)");
644
            $output->writeln('');
645
            $c++;
646
        }
647
    }
648
}
649