Completed
Push — master ( ad0611...abd676 )
by Tom
09:08 queued 04:30
created

Application::isMagerunStopFileFound()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace N98\Magento;
4
5
use Composer\Autoload\ClassLoader;
6
use Magento\Framework\ObjectManager\ObjectManager;
7
use Magento\Mtf\EntryPoint\EntryPoint;
8
use N98\Magento\Application\Config;
9
use N98\Magento\Application\ConfigurationLoader;
10
use N98\Magento\Application\Console\Events;
11
use N98\Util\Console\Helper\MagentoHelper;
12
use N98\Util\Console\Helper\TwigHelper;
13
use N98\Util\OperatingSystem;
14
use Symfony\Component\Console\Application as BaseApplication;
15
use Symfony\Component\Console\Command\Command;
16
use Symfony\Component\Console\Event\ConsoleEvent;
17
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
18
use Symfony\Component\Console\Input\ArgvInput;
19
use Symfony\Component\Console\Input\InputDefinition;
20
use Symfony\Component\Console\Input\InputInterface;
21
use Symfony\Component\Console\Input\InputOption;
22
use Symfony\Component\Console\Output\ConsoleOutput;
23
use Symfony\Component\Console\Output\NullOutput;
24
use Symfony\Component\Console\Output\OutputInterface;
25
use Symfony\Component\EventDispatcher\EventDispatcher;
26
use UnexpectedValueException;
27
28
class Application extends BaseApplication
29
{
30
    /**
31
     * @var string
32
     */
33
    const APP_NAME = 'n98-magerun2';
34
35
    /**
36
     * @var string
37
     */
38
    const APP_VERSION = '1.1.11';
39
40
    /**
41
     * @var int
42
     */
43
    const MAGENTO_MAJOR_VERSION_1 = 1;
44
45
    /**
46
     * @var int
47
     */
48
    const MAGENTO_MAJOR_VERSION_2 = 2;
49
50
    /**
51
     * @var string
52
     */
53
    private static $logo = "
54
          ____  ____                                                   ___ 
55
   ____  / __ \\( __ )      ____ ___  ____ _____ ____  _______  ______ |__ \\
56
  / __ \\/ /_/ / __  |_____/ __ `__ \\/ __ `/ __ `/ _ \\/ ___/ / / / __ \\__/ /
57
 / / / /\\__, / /_/ /_____/ / / / / / /_/ / /_/ /  __/ /  / /_/ / / / / __/
58
/_/ /_//____/\\____/     /_/ /_/ /_/\\__,_/\\__, /\\___/_/   \\__,_/_/ /_/____/
59
                                        /____/                             
60
";
61
    /**
62
     * @var ClassLoader
63
     */
64
    protected $autoloader;
65
66
    /**
67
     * @var Config
68
     */
69
    protected $config;
70
71
    /**
72
     * @var string
73
     */
74
    protected $_magentoRootFolder = null;
75
76
    /**
77
     * @var bool
78
     */
79
    protected $_magentoEnterprise = false;
80
81
    /**
82
     * @var int
83
     */
84
    protected $_magentoMajorVersion = self::MAGENTO_MAJOR_VERSION_2;
85
86
    /**
87
     * @var EntryPoint
88
     */
89
    protected $_magento2EntryPoint = null;
90
91
    /**
92
     * @var bool
93
     */
94
    protected $_isPharMode = false;
95
96
    /**
97
     * @var bool
98
     */
99
    protected $_magerunStopFileFound = false;
100
101
    /**
102
     * @var string
103
     */
104
    protected $_magerunStopFileFolder = null;
105
106
    /**
107
     * @var bool
108
     */
109
    protected $_isInitialized = false;
110
111
    /**
112
     * @var EventDispatcher
113
     */
114
    protected $dispatcher;
115
116
    /**
117
     * If root dir is set by root-dir option this flag is true
118
     *
119
     * @var bool
120
     */
121
    protected $_directRootDir = false;
122
123
    /**
124
     * @var bool
125
     */
126
    protected $_magentoDetected = false;
127
128
    /**
129
     * @var ObjectManager
130
     */
131
    protected $_objectManager = null;
132
133
    /**
134
     * @param ClassLoader $autoloader
0 ignored issues
show
Documentation introduced by
Should the type for parameter $autoloader not be ClassLoader|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
135
     */
136
    public function __construct($autoloader = null)
137
    {
138
        $this->autoloader = $autoloader;
139
        parent::__construct(self::APP_NAME, self::APP_VERSION);
140
    }
141
142
    /**
143
     * @return InputDefinition
144
     */
145
    protected function getDefaultInputDefinition()
146
    {
147
        $inputDefinition = parent::getDefaultInputDefinition();
148
149
        /**
150
         * Root dir
151
         */
152
        $rootDirOption = new InputOption(
153
            '--root-dir',
154
            '',
155
            InputOption::VALUE_OPTIONAL,
156
            'Force magento root dir. No auto detection'
157
        );
158
        $inputDefinition->addOption($rootDirOption);
159
160
        /**
161
         * Skip config
162
         */
163
        $skipExternalConfig = new InputOption(
164
            '--skip-config',
165
            '',
166
            InputOption::VALUE_NONE,
167
            'Do not load any custom config.'
168
        );
169
        $inputDefinition->addOption($skipExternalConfig);
170
171
        /**
172
         * Skip root check
173
         */
174
        $skipExternalConfig = new InputOption(
175
            '--skip-root-check',
176
            '',
177
            InputOption::VALUE_NONE,
178
            'Do not check if n98-magerun runs as root'
179
        );
180
        $inputDefinition->addOption($skipExternalConfig);
181
182
        /**
183
         * Skip core commands
184
         */
185
        $skipMagento2CoreCommands = new InputOption(
186
            '--skip-core-commands',
187
            '',
188
            InputOption::VALUE_OPTIONAL,
189
            'Do not include Magento 2 core commands'
190
        );
191
        $inputDefinition->addOption($skipMagento2CoreCommands);
192
193
        return $inputDefinition;
194
    }
195
196
    /**
197
     * Search for magento root folder
198
     *
199
     * @param InputInterface $input [optional]
1 ignored issue
show
Documentation introduced by
Should the type for parameter $input not be null|InputInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
200
     * @param OutputInterface $output [optional]
0 ignored issues
show
Documentation introduced by
Should the type for parameter $output not be null|OutputInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
201
     * @return void
202
     */
203
    public function detectMagento(InputInterface $input = null, OutputInterface $output = null)
204
    {
205
        // do not detect magento twice
206
        if ($this->_magentoDetected) {
207
            return;
208
        }
209
210
        if ($this->getMagentoRootFolder() === null) {
211
            $this->_checkRootDirOption();
212
            $folder = OperatingSystem::getCwd();
213
        } else {
214
            $folder = $this->getMagentoRootFolder();
215
        }
216
217
        $this->getHelperSet()->set(new MagentoHelper($input, $output), 'magento');
218
        $magentoHelper = $this->getHelperSet()->get('magento');
219
        /* @var $magentoHelper MagentoHelper */
220
        if (!$this->_directRootDir) {
221
            $subFolders = $this->config->getDetectSubFolders();
222
        } else {
223
            $subFolders = array();
224
        }
225
226
        $this->_magentoDetected = $magentoHelper->detect($folder, $subFolders);
227
        $this->_magentoRootFolder = $magentoHelper->getRootFolder();
228
        $this->_magentoEnterprise = $magentoHelper->isEnterpriseEdition();
229
        $this->_magentoMajorVersion = $magentoHelper->getMajorVersion();
230
        $this->_magerunStopFileFound = $magentoHelper->isMagerunStopFileFound();
231
        $this->_magerunStopFileFolder = $magentoHelper->getMagerunStopFileFolder();
232
    }
233
234
    /**
235
     * Add own helpers to helperset.
236
     *
237
     * @return void
238
     */
239
    protected function registerHelpers()
240
    {
241
        $helperSet = $this->getHelperSet();
242
        $config = $this->config->getConfig();
243
244
        // Twig
245
        $twigBaseDirs = array(
246
            __DIR__ . '/../../../res/twig'
247
        );
248
        if (isset($config['twig']['baseDirs']) && is_array($config['twig']['baseDirs'])) {
249
            $twigBaseDirs = array_merge(array_reverse($config['twig']['baseDirs']), $twigBaseDirs);
250
        }
251
        $helperSet->set(new TwigHelper($twigBaseDirs), 'twig');
252
253
        foreach ($config['helpers'] as $helperName => $helperClass) {
254
            if (class_exists($helperClass)) {
255
                $helperSet->set(new $helperClass(), $helperName);
256
            }
257
        }
258
    }
259
260
    /**
261
     * Try to bootstrap magento 2 and load cli application
262
     *
263
     * @param OutputInterface $output
264
     */
265
    protected function registerMagentoCoreCommands(OutputInterface $output)
266
    {
267
        if ($this->getMagentoRootFolder()) {
268
            // Magento was found -> register core cli commands
269
            require_once $this->getMagentoRootFolder() . '/app/bootstrap.php';
270
271
            $coreCliApplication = new \Magento\Framework\Console\Cli();
272
            $coreCliApplicationCommands = $coreCliApplication->all();
273
274
            foreach ($coreCliApplicationCommands as $coreCliApplicationCommand) {
275
                if (OutputInterface::VERBOSITY_DEBUG <= $output->getVerbosity()) {
276
                    $output->writeln(
277
                        sprintf(
278
                            '<debug>Add core command </debug> <info>%s</info> -> <comment>%s</comment>',
279
                            $coreCliApplicationCommand->getName(),
280
                            get_class($coreCliApplicationCommand)
281
                        )
282
                    );
283
                }
284
                $this->add($coreCliApplicationCommand);
285
            }
286
        }
287
    }
288
289
    /**
290
     * Override standard command registration. We want alias support.
291
     *
292
     * @param \Symfony\Component\Console\Command\Command $command
293
     * @return \Symfony\Component\Console\Command\Command
0 ignored issues
show
Documentation introduced by
Should the return type not be Command|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
294
     */
295
    public function add(Command $command)
296
    {
297
        if ($this->config) {
298
            $this->config->registerConfigCommandAlias($command);
299
        }
300
301
        return parent::add($command);
302
    }
303
304
    /**
305
     * @param bool $mode
306
     */
307
    public function setPharMode($mode)
308
    {
309
        $this->_isPharMode = $mode;
310
    }
311
312
    /**
313
     * @return bool
314
     */
315
    public function isPharMode()
316
    {
317
        return $this->_isPharMode;
318
    }
319
320
    /**
321
     * @TODO Move logic into "EventSubscriber"
322
     *
323
     * @param OutputInterface $output
324
     * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be null|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
325
     */
326
    public function checkVarDir(OutputInterface $output)
327
    {
328
        $tempVarDir = sys_get_temp_dir() . '/magento/var';
329
        if (!OutputInterface::VERBOSITY_NORMAL <= $output->getVerbosity() && !is_dir($tempVarDir)) {
330
            return;
331
        }
332
333
        $this->detectMagento(null, $output);
334
        /* If magento is not installed yet, don't check */
335
        if ($this->_magentoRootFolder === null
336
            || !file_exists($this->_magentoRootFolder . '/app/etc/local.xml')
337
        ) {
338
            return;
339
        }
340
341
        try {
342
            $this->initMagento();
343
        } catch (\Exception $e) {
344
            $message = 'Cannot initialize Magento. Please check your configuration. '
345
                . 'Some n98-magerun command will not work. Got message: ';
346
            if (OutputInterface::VERBOSITY_VERY_VERBOSE <= $output->getVerbosity()) {
347
                $message .= $e->getTraceAsString();
348
            } else {
349
                $message .= $e->getMessage();
350
            }
351
            $output->writeln($message);
352
353
            return;
354
        }
355
356
        $configOptions = new \Mage_Core_Model_Config_Options();
357
        $currentVarDir = $configOptions->getVarDir();
358
359
        if ($currentVarDir == $tempVarDir) {
360
            $output->writeln(
361
                sprintf('<warning>Fallback folder %s is used in n98-magerun</warning>', $tempVarDir)
362
            );
363
            $output->writeln('');
364
            $output->writeln(
365
                'n98-magerun is using the fallback folder. If there is another folder configured for Magento, '
366
                . 'this can cause serious problems.'
367
            );
368
            $output->writeln(
369
                'Please refer to https://github.com/netz98/n98-magerun/wiki/File-system-permissions '
370
                . 'for more information.'
371
            );
372
            $output->writeln('');
373
        } else {
374
            $output->writeln(sprintf(
375
                '<warning>Folder %s found, but not used in n98-magerun</warning>',
376
                $tempVarDir
377
            ));
378
            $output->writeln('');
379
            $output->writeln(
380
                sprintf(
381
                    'This might cause serious problems. n98-magerun is using the configured var-folder '
382
                    . '<comment>%s</comment>',
383
                    $currentVarDir
384
                )
385
            );
386
            $output->writeln(
387
                'Please refer to https://github.com/netz98/n98-magerun/wiki/File-system-permissions '
388
                . 'for more information.'
389
            );
390
            $output->writeln('');
391
392
            return false;
393
        }
394
    }
395
396
    /**
397
     * Loads and initializes the Magento application
398
     *
399
     * @return bool false if magento root folder is not set, true otherwise
400
     */
401
    public function initMagento()
402
    {
403
        if ($this->getMagentoRootFolder() !== null) {
404
            if ($this->_magentoMajorVersion == self::MAGENTO_MAJOR_VERSION_2) {
405
                $this->_initMagento2();
406
            } else {
407
                $this->_initMagento1();
408
            }
409
410
            return true;
411
        }
412
413
        return false;
414
    }
415
416
    /**
417
     * @return string
418
     */
419
    public function getHelp()
420
    {
421
        return self::$logo . parent::getHelp();
422
    }
423
424
    public function getLongVersion()
425
    {
426
        return parent::getLongVersion() . ' by <info>netz98 new media GmbH</info>';
427
    }
428
429
    /**
430
     * @return boolean
431
     */
432
    public function isMagentoEnterprise()
433
    {
434
        return $this->_magentoEnterprise;
435
    }
436
437
    /**
438
     * @return string
439
     */
440
    public function getMagentoRootFolder()
441
    {
442
        return $this->_magentoRootFolder;
443
    }
444
445
    /**
446
     * @param string $magentoRootFolder
447
     */
448
    public function setMagentoRootFolder($magentoRootFolder)
449
    {
450
        $this->_magentoRootFolder = $magentoRootFolder;
451
    }
452
453
    /**
454
     * @return int
455
     */
456
    public function getMagentoMajorVersion()
457
    {
458
        return $this->_magentoMajorVersion;
459
    }
460
461
    /**
462
     * @return ClassLoader
463
     */
464
    public function getAutoloader()
465
    {
466
        return $this->autoloader;
467
    }
468
469
    /**
470
     * @param ClassLoader $autoloader
471
     */
472
    public function setAutoloader(ClassLoader $autoloader)
473
    {
474
        $this->autoloader = $autoloader;
475
    }
476
477
    /**
478
     * @return array
479
     */
480
    public function getConfig()
481
    {
482
        return $this->config->getConfig();
483
    }
484
485
    /**
486
     * @param array $config
487
     */
488
    public function setConfig($config)
489
    {
490
        $this->config->setConfig($config);
491
    }
492
493
    /**
494
     * @return boolean
495
     */
496
    public function isMagerunStopFileFound()
497
    {
498
        return $this->_magerunStopFileFound;
499
    }
500
501
    /**
502
     * Runs the current application with possible command aliases
503
     *
504
     * @param InputInterface $input An Input instance
505
     * @param OutputInterface $output An Output instance
506
     *
507
     * @return integer 0 if everything went fine, or an error code
508
     */
509
    public function doRun(InputInterface $input, OutputInterface $output)
510
    {
511
        $event = new Application\Console\Event($this, $input, $output);
512
        $this->dispatcher->dispatch(Events::RUN_BEFORE, $event);
513
514
        /**
515
         * only for compatibility to old versions.
516
         */
517
        $event = new ConsoleEvent(new Command('dummy'), $input, $output);
518
        $this->dispatcher->dispatch('console.run.before', $event);
519
520
        $input = $this->config->checkConfigCommandAlias($input);
521
        if ($output instanceof ConsoleOutput) {
522
            $this->checkVarDir($output->getErrorOutput());
523
        }
524
525
        return parent::doRun($input, $output);
526
    }
527
528
    /**
529
     * @param InputInterface $input [optional]
1 ignored issue
show
Documentation introduced by
Should the type for parameter $input not be null|InputInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
530
     * @param OutputInterface $output [optional]
0 ignored issues
show
Documentation introduced by
Should the type for parameter $output not be null|OutputInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
531
     *
532
     * @return int
533
     */
534
    public function run(InputInterface $input = null, OutputInterface $output = null)
535
    {
536
        if (null === $input) {
537
            $input = new ArgvInput();
538
        }
539
540
        if (null === $output) {
541
            $output = new ConsoleOutput();
542
        }
543
        $this->_addOutputStyles($output);
544
        if ($output instanceof ConsoleOutput) {
545
            $this->_addOutputStyles($output->getErrorOutput());
546
        }
547
548
        $this->configureIO($input, $output);
549
550
        try {
551
            $this->init(array(), $input, $output);
552
        } catch (\Exception $e) {
553
            $output = new ConsoleOutput();
554
            $this->renderException($e, $output);
555
        }
556
557
        $return = parent::run($input, $output);
558
559
        // Fix for no return values -> used in interactive shell to prevent error output
560
        if ($return === null) {
561
            return 0;
562
        }
563
564
        return $return;
565
    }
566
567
    /**
568
     * @param array $initConfig
569
     * @param InputInterface $input
1 ignored issue
show
Documentation introduced by
Should the type for parameter $input not be null|InputInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
570
     * @param OutputInterface $output
0 ignored issues
show
Documentation introduced by
Should the type for parameter $output not be null|OutputInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
571
     *
572
     * @return void
573
     */
574
    public function init(array $initConfig = array(), InputInterface $input = null, OutputInterface $output = null)
575
    {
576
        if ($this->_isInitialized) {
577
            return;
578
        }
579
580
        // Suppress DateTime warnings
581
        date_default_timezone_set(@date_default_timezone_get());
582
583
        // Initialize EventDispatcher early
584
        $this->dispatcher = new EventDispatcher();
585
        $this->setDispatcher($this->dispatcher);
586
587
        if (null === $input) {
588
            $input = new ArgvInput();
589
        }
590
591
        if (null === $output) {
592
            $output = new ConsoleOutput();
593
        }
594
595
        if (null !== $this->config) {
596
            throw new UnexpectedValueException(sprintf('Config already initialized'));
597
        }
598
599
        $loadExternalConfig = !$this->_checkSkipConfigOption();
600
601
        $this->config = $config = new Config($initConfig, $this->isPharMode(), $output);
602
        $configLoader = $config->getLoader();
603
        $config->loadPartialConfig($loadExternalConfig);
604
        $this->detectMagento($input, $output);
605
        $configLoader->loadStageTwo($this->_magentoRootFolder, $loadExternalConfig, $this->_magerunStopFileFolder);
606
        $config->load();
607
608
        if ($autoloader = $this->autoloader) {
609
610
            /**
611
             * Include commands shipped by Magento 2 core
612
             */
613
            if (!$this->_checkSkipMagento2CoreCommandsOption()) {
614
                $this->registerMagentoCoreCommands($output);
615
            }
616
617
            $this->config->registerCustomAutoloaders($autoloader);
618
            $this->registerEventSubscribers();
619
            $config->registerCustomCommands($this);
620
        }
621
622
        $this->registerHelpers();
623
624
        $this->_isInitialized = true;
625
    }
626
627
    /**
628
     * @param array $initConfig [optional]
629
     * @param InputInterface $input [optional]
1 ignored issue
show
Documentation introduced by
Should the type for parameter $input not be null|InputInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
630
     * @param OutputInterface $output [optional]
0 ignored issues
show
Documentation introduced by
Should the type for parameter $output not be null|OutputInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
631
     */
632
    public function reinit($initConfig = array(), InputInterface $input = null, OutputInterface $output = null)
633
    {
634
        $this->_isInitialized = false;
635
        $this->config = null;
636
        $this->init($initConfig, $input, $output);
637
    }
638
639
    /**
640
     * @return void
641
     */
642
    protected function registerEventSubscribers()
643
    {
644
        foreach ($this->config->getConfig()['event']['subscriber'] as $subscriberClass) {
645
            $subscriber = new $subscriberClass();
646
            $this->dispatcher->addSubscriber($subscriber);
647
        }
648
    }
649
650
    /**
651
     * @return bool
652
     */
653
    protected function _checkSkipConfigOption()
654
    {
655
        $skipConfigOption = getopt('', array('skip-config'));
656
657
        return count($skipConfigOption) > 0;
658
    }
659
660
    /**
661
     * @return bool
662
     */
663
    protected function _checkSkipMagento2CoreCommandsOption()
664
    {
665
        $skipConfigOption = getopt('', array('skip-core-commands'));
666
667
        getenv('MAGERUN_SKIP_CORE_COMMANDS') && $skipConfigOption[] = 1;
668
669
        return count($skipConfigOption) > 0;
670
    }
671
672
    /**
673
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
674
     */
675
    protected function _checkRootDirOption()
676
    {
677
        $specialGlobalOptions = getopt('', array('root-dir:'));
678
679
        if (count($specialGlobalOptions) > 0) {
680
            if (isset($specialGlobalOptions['root-dir'][0])
681
                && $specialGlobalOptions['root-dir'][0] == '~'
682
            ) {
683
                $specialGlobalOptions['root-dir'] = OperatingSystem::getHomeDir() .
684
                    substr($specialGlobalOptions['root-dir'], 1);
685
            }
686
            $folder = realpath($specialGlobalOptions['root-dir']);
687
            $this->_directRootDir = true;
688
            if (is_dir($folder)) {
689
                chdir($folder);
690
691
                return;
692
            }
693
        }
694
    }
695
696
    protected function _initMagento1()
697
    {
698
        $magento1Hint = <<<'MAGENTO1HINT'
699
You are running a Magento 1.x instance. This version of n98-magerun is not compatible
700
with Magento 1.x. Please use n98-magerun (version 1) for this shop.
701
702
A current version of the software can be downloaded on github.
703
704
<info>Download with curl
705
------------------</info>
706
707
    <comment>curl -O https://files.magerun.net/n98-magerun.phar</comment>
708
709
<info>Download with wget
710
------------------</info>
711
712
    <comment>wget https://files.magerun.net/n98-magerun.phar</comment>
713
714
MAGENTO1HINT;
715
716
        $output = new ConsoleOutput();
717
718
        $output->writeln(array(
719
            '',
720
            $this->getHelperSet()->get('formatter')->formatBlock('Compatibility Notice', 'bg=blue;fg=white', true),
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Symfony\Component\Console\Helper\HelperInterface as the method formatBlock() does only exist in the following implementations of said interface: Symfony\Component\Console\Helper\FormatterHelper.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
721
            ''
722
        ));
723
724
        $output->writeln($magento1Hint);
725
        exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method _initMagento1() 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...
726
    }
727
728
    /**
729
     * @return void
730
     */
731
    protected function _initMagento2()
0 ignored issues
show
Coding Style introduced by
_initMagento2 uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
732
    {
733
        require_once $this->getMagentoRootFolder() . '/app/bootstrap.php';
734
735
        $params = $_SERVER;
736
        $params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE] = 'admin';
737
        $params[\Magento\Store\Model\Store::CUSTOM_ENTRY_POINT_PARAM] = true;
738
        $params['entryPoint'] = basename(__FILE__);
739
740
        $bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $params);
741
        /** @var \Magento\Framework\App\Cron $app */
742
        $app = $bootstrap->createApplication('N98\Magento\Framework\App\Magerun', []);
743
        /* @var $app \N98\Magento\Framework\App\Magerun */
744
        $app->launch();
745
746
        $this->_objectManager = $app->getObjectManager();
0 ignored issues
show
Documentation Bug introduced by
It seems like $app->getObjectManager() of type object<Magento\Framework\ObjectManagerInterface> is incompatible with the declared type object<Magento\Framework...tManager\ObjectManager> of property $_objectManager.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
747
    }
748
749
    /**
750
     * @return EventDispatcher
751
     */
752
    public function getDispatcher()
753
    {
754
        return $this->dispatcher;
755
    }
756
757
    /**
758
     * @param ConfigurationLoader $configurationLoader
759
     */
760
    public function setConfigurationLoader(ConfigurationLoader $configurationLoader)
761
    {
762
        $this->config->setConfigurationLoader($configurationLoader);
763
    }
764
765
    /**
766
     * @param OutputInterface $output
767
     */
768
    protected function _addOutputStyles(OutputInterface $output)
769
    {
770
        $output->getFormatter()->setStyle('debug', new OutputFormatterStyle('magenta', 'white'));
771
        $output->getFormatter()->setStyle('warning', new OutputFormatterStyle('red', 'yellow', array('bold')));
772
    }
773
774
    /**
775
     * @return ObjectManager
776
     */
777
    public function getObjectManager()
778
    {
779
        return $this->_objectManager;
780
    }
781
}
782