AbstractMagentoCommand::requireEnterprise()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
1
<?php
2
3
namespace N98\Magento\Command;
4
5
use Composer\Factory as ComposerFactory;
6
use Composer\IO\ConsoleIO;
7
use Composer\Package\Loader\ArrayLoader as PackageLoader;
8
use Composer\Package\PackageInterface;
9
use Mage;
10
use Magento\Framework\ObjectManager\ObjectManager;
11
use N98\Magento\Command\SubCommand\ConfigBag;
12
use N98\Magento\Command\SubCommand\SubCommandFactory;
13
use Symfony\Component\Console\Command\Command;
14
use Symfony\Component\Console\Helper\FormatterHelper;
15
use Symfony\Component\Console\Input\InputInterface;
16
use Symfony\Component\Console\Output\OutputInterface;
17
18
/**
19
 * Class AbstractMagentoCommand
20
 *
21
 * @package N98\Magento\Command
22
 *
23
 * @method \N98\Magento\Application getApplication() getApplication()
24
 */
25
abstract class AbstractMagentoCommand extends Command
26
{
27
    /**
28
     * @var int
29
     */
30
    const MAGENTO_MAJOR_VERSION_2 = 2;
31
32
    /**
33
     * @var string
34
     */
35
    protected $_magentoRootFolder = null;
36
37
    /**
38
     * @var int
39
     */
40
    protected $_magentoMajorVersion = self::MAGENTO_MAJOR_VERSION_2;
41
42
    /**
43
     * @var bool
44
     */
45
    protected $_magentoEnterprise = false;
46
47
    /**
48
     * @var array
49
     */
50
    protected $_deprecatedAlias = array();
51
52
    /**
53
     * @var array
54
     */
55
    protected $_websiteCodeMap = array();
56
57
    /**
58
     * @var ObjectManager
59
     */
60
    protected $_objectManager = null;
61
62
    /**
63
     * Initializes the command just after the input has been validated.
64
     *
65
     * This is mainly useful when a lot of commands extends one main command
66
     * where some things need to be initialized based on the input arguments and options.
67
     *
68
     * @param InputInterface $input An InputInterface instance
69
     * @param OutputInterface $output An OutputInterface instance
70
     */
71
    protected function initialize(InputInterface $input, OutputInterface $output)
72
    {
73
        $this->checkDeprecatedAliases($input, $output);
74
    }
75
76
    /**
77
     * @return ObjectManager
78
     */
79
    protected function getObjectManager()
80
    {
81
        return $this->getApplication()->getObjectManager();
82
    }
83
84
    /**
85
     * @param array $codeArgument
86
     * @param bool $status
87
     * @return void
88
     */
89
    protected function saveCacheStatus($codeArgument, $status)
90
    {
91
        $cacheTypes = $this->_getCacheModel()->getTypes();
0 ignored issues
show
Bug introduced by
The method _getCacheModel() does not seem to exist on object<N98\Magento\Comma...AbstractMagentoCommand>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
92
        $enable = Mage::app()->useCache();
93
        foreach ($cacheTypes as $cacheCode => $cacheModel) {
94
            if (empty($codeArgument) || in_array($cacheCode, $codeArgument)) {
95
                $enable[$cacheCode] = $status ? 1 : 0;
96
            }
97
        }
98
99
        Mage::app()->saveUseCache($enable);
100
    }
101
102
    private function _initWebsites()
103
    {
104
        $this->_websiteCodeMap = array();
105
        /** @var \Mage_Core_Model_Website[] $websites */
106
        $websites = Mage::app()->getWebsites(false);
107
        foreach ($websites as $website) {
108
            $this->_websiteCodeMap[$website->getId()] = $website->getCode();
109
        }
110
    }
111
112
    /**
113
     * @param int $websiteId
114
     * @return string
115
     */
116
    protected function _getWebsiteCodeById($websiteId)
117
    {
118
        if (empty($this->_websiteCodeMap)) {
119
            $this->_initWebsites();
120
        }
121
122
        if (isset($this->_websiteCodeMap[$websiteId])) {
123
            return $this->_websiteCodeMap[$websiteId];
124
        }
125
126
        return '';
127
    }
128
129
    /**
130
     * @param string $websiteCode
131
     * @return int
132
     */
133
    protected function _getWebsiteIdByCode($websiteCode)
134
    {
135
        if (empty($this->_websiteCodeMap)) {
136
            $this->_initWebsites();
137
        }
138
        $websiteMap = array_flip($this->_websiteCodeMap);
139
140
        return $websiteMap[$websiteCode];
141
    }
142
143
    /**
144
     * @param string|null $commandClass
145
     * @return array
146
     */
147
    protected function getCommandConfig($commandClass = null)
148
    {
149
        if ($commandClass == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $commandClass of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
150
            $commandClass = get_class($this);
151
        }
152
        $configArray = $this->getApplication()->getConfig();
153
        if (isset($configArray['commands'][$commandClass])) {
154
            return $configArray['commands'][$commandClass];
155
        }
156
157
        return null;
158
    }
159
160
    /**
161
     * @param OutputInterface $output
162
     * @param string $text
163
     * @param string $style
164
     */
165
    protected function writeSection(OutputInterface $output, $text, $style = 'bg=blue;fg=white')
166
    {
167
        /** @var $formatter FormatterHelper */
168
        $formatter = $this->getHelper('formatter');
169
170
        $output->writeln(array(
171
            '',
172
            $formatter->formatBlock($text, $style, true),
173
            '',
174
        ));
175
    }
176
177
    /**
178
     * Bootstrap magento shop
179
     *
180
     * @return bool
181
     */
182
    protected function initMagento()
183
    {
184
        $init = $this->getApplication()->initMagento();
185
        if ($init) {
186
            $this->_magentoRootFolder = $this->getApplication()->getMagentoRootFolder();
187
        }
188
189
        return $init;
190
    }
191
192
    /**
193
     * Search for magento root folder
194
     *
195
     * @param OutputInterface $output
196
     * @param bool $silent print debug messages
197
     * @throws \RuntimeException
198
     */
199
    public function detectMagento(OutputInterface $output, $silent = true)
200
    {
201
        $this->getApplication()->detectMagento();
202
203
        $this->_magentoEnterprise = $this->getApplication()->isMagentoEnterprise();
204
        $this->_magentoRootFolder = $this->getApplication()->getMagentoRootFolder();
205
        $this->_magentoMajorVersion = $this->getApplication()->getMagentoMajorVersion();
206
207
        if (!$silent) {
208
            $editionString = ($this->_magentoEnterprise ? ' (Enterprise Edition) ' : '');
209
            $output->writeln(
210
                '<info>Found Magento ' . $editionString . 'in folder "' . $this->_magentoRootFolder . '"</info>'
211
            );
212
        }
213
214
        if (!empty($this->_magentoRootFolder)) {
215
            return;
216
        }
217
218
        throw new \RuntimeException('Magento folder could not be detected');
219
    }
220
221
    /**
222
     * Die if not Enterprise
223
     */
224
    protected function requireEnterprise(OutputInterface $output)
225
    {
226
        if (!$this->_magentoEnterprise) {
227
            $output->writeln('<error>Enterprise Edition is required but was not detected</error>');
228
            exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method requireEnterprise() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
229
        }
230
    }
231
232
    /**
233
     * @return \Mage_Core_Helper_Data
234
     */
235
    protected function getCoreHelper()
236
    {
237
        if ($this->_magentoMajorVersion == self::MAGENTO_MAJOR_VERSION_2) {
238
            return Mage::helper('Mage_Core_Helper_Data');
239
        }
240
241
        return Mage::helper('core');
242
    }
243
244
    /**
245
     * @param InputInterface $input
246
     * @param OutputInterface $output
247
     * @return \Composer\Downloader\DownloadManager
248
     */
249
    public function getComposerDownloadManager($input, $output)
250
    {
251
        return $this->getComposer($input, $output)->getDownloadManager();
252
    }
253
254
    /**
255
     * @param array|PackageInterface $config
256
     * @return \Composer\Package\CompletePackage
257
     */
258
    public function createComposerPackageByConfig($config)
259
    {
260
        $packageLoader = new PackageLoader();
261
262
        return $packageLoader->load($config);
0 ignored issues
show
Bug introduced by
It seems like $config defined by parameter $config on line 258 can also be of type object<Composer\Package\PackageInterface>; however, Composer\Package\Loader\ArrayLoader::load() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
263
    }
264
265
    /**
266
     * @param InputInterface $input
267
     * @param OutputInterface $output
268
     * @param array|PackageInterface $config
269
     * @param string $targetFolder
270
     * @param bool $preferSource
271
     * @return \Composer\Package\CompletePackage
272
     */
273
    public function downloadByComposerConfig(
274
        InputInterface $input,
275
        OutputInterface $output,
276
        $config,
277
        $targetFolder,
278
        $preferSource = true
279
    ) {
280
        $dm = $this->getComposerDownloadManager($input, $output);
281
        if (!$config instanceof PackageInterface) {
282
            $package = $this->createComposerPackageByConfig($config);
283
        } else {
284
            $package = $config;
285
        }
286
287
        $helper = new \N98\Util\Console\Helper\MagentoHelper();
288
        $helper->detect($targetFolder);
289
        if ($this->isSourceTypeRepository($package->getSourceType()) && $helper->getRootFolder() == $targetFolder) {
290
            $package->setInstallationSource('source');
291
            $this->checkRepository($package, $targetFolder);
292
            $dm->update($package, $package, $targetFolder);
293
        } else {
294
            $dm->download($package, $targetFolder, $preferSource);
295
        }
296
297
        return $package;
298
    }
299
300
    /**
301
     * brings locally cached repository up to date if it is missing the requested tag
302
     *
303
     * @param PackageInterface $package
304
     * @param string $targetFolder
305
     */
306
    protected function checkRepository(PackageInterface $package, $targetFolder)
307
    {
308
        if ($package->getSourceType() == 'git') {
309
            $command = sprintf(
310
                'cd %s && git rev-parse refs/tags/%s',
311
                escapeshellarg($targetFolder),
312
                escapeshellarg($package->getSourceReference())
313
            );
314
            $existingTags = shell_exec($command);
315
            if (!$existingTags) {
316
                $command = sprintf('cd %s && git fetch', escapeshellarg($targetFolder));
317
                shell_exec($command);
318
            }
319
        } elseif ($package->getSourceType() == 'hg') {
320
            $command = sprintf(
321
                'cd %s && hg log --template "{tags}" -r %s',
322
                escapeshellarg($targetFolder),
323
                escapeshellarg($package->getSourceReference())
324
            );
325
            $existingTag = shell_exec($command);
326
            if ($existingTag === $package->getSourceReference()) {
327
                $command = sprintf('cd %s && hg pull', escapeshellarg($targetFolder));
328
                shell_exec($command);
329
            }
330
        }
331
    }
332
333
    /**
334
     * @param string $type
335
     *
336
     * @return bool
337
     */
338
    public function isSourceTypeRepository($type)
339
    {
340
        return in_array($type, array('git', 'hg'));
341
    }
342
343
    /**
344
     * obtain composer
345
     *
346
     * @param InputInterface $input
347
     * @param OutputInterface $output
348
     *
349
     * @return \Composer\Composer
350
     */
351
    public function getComposer(InputInterface $input, OutputInterface $output)
352
    {
353
        $io = new ConsoleIO($input, $output, $this->getHelperSet());
0 ignored issues
show
Bug introduced by
It seems like $this->getHelperSet() can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
354
        $config = array(
355
            'config' => array(
356
                'secure-http' => false,
357
            ),
358
        );
359
360
        return ComposerFactory::create($io, $config);
361
    }
362
363
    /**
364
     * @param string $alias
365
     * @param string $message
366
     * @return AbstractMagentoCommand
367
     */
368
    protected function addDeprecatedAlias($alias, $message)
369
    {
370
        $this->_deprecatedAlias[$alias] = $message;
371
372
        return $this;
373
    }
374
375
    /**
376
     * @param InputInterface $input
377
     * @param OutputInterface $output
378
     */
379
    protected function checkDeprecatedAliases(InputInterface $input, OutputInterface $output)
380
    {
381
        if (isset($this->_deprecatedAlias[$input->getArgument('command')])) {
382
            $output->writeln(
383
                '<error>Deprecated:</error> <comment>' . $this->_deprecatedAlias[$input->getArgument('command')] .
384
                '</comment>'
385
            );
386
        }
387
    }
388
389
    /**
390
     * @param string $value
391
     * @return bool
392
     */
393
    protected function _parseBoolOption($value)
394
    {
395
        return in_array(strtolower($value), array('y', 'yes', 1, 'true'));
396
    }
397
398
    /**
399
     * @param string $value
400
     * @return bool
401
     */
402
    public function parseBoolOption($value)
403
    {
404
        return $this->_parseBoolOption($value);
405
    }
406
407
    /**
408
     * @param string $value
409
     * @return string
410
     */
411
    public function formatActive($value)
412
    {
413
        if (in_array($value, array(1, 'true'))) {
414
            return 'active';
415
        }
416
417
        return 'inactive';
418
    }
419
420
    /**
421
     * @param InputInterface $input
422
     * @param OutputInterface $output
423
     *
424
     * @return int
425
     */
426
    public function run(InputInterface $input, OutputInterface $output)
427
    {
428
        $this->getHelperSet()->setCommand($this);
429
430
        $this->injectObjects($output);
431
432
        return parent::run($input, $output);
433
    }
434
435
    /**
436
     * @param OutputInterface $output
437
     */
438
    public function injectObjects(OutputInterface $output)
439
    {
440
        /* @var $injectionHelper InjectionHelper */
441
        if (method_exists($this, 'inject')) {
442
            $this->detectMagento($output);
443
            $this->initMagento();
444
            $injectionHelper = $this->getHelper('injection');
445
            $injectionHelper->methodInjection(
446
                $this,
447
                'inject',
448
                $this->getObjectManager()
449
            );
450
        }
451
    }
452
453
    /**
454
     * @param InputInterface $input
455
     * @param OutputInterface $output
456
     * @param string $baseNamespace If this is set we can use relative class names.
457
     *
458
     * @return SubCommandFactory
459
     */
460
    protected function createSubCommandFactory(
461
        InputInterface $input,
462
        OutputInterface $output,
463
        $baseNamespace = ''
464
    ) {
465
        $configBag = new ConfigBag();
466
467
        $commandConfig = $this->getCommandConfig();
468
        if (empty($commandConfig)) {
469
            $commandConfig = array();
470
        }
471
472
        return new SubCommandFactory(
473
            $this,
474
            $baseNamespace,
475
            $input,
476
            $output,
477
            $commandConfig,
478
            $configBag
479
        );
480
    }
481
}
482