Completed
Push — master ( 8c3306...57acb7 )
by Martijn van
02:51
created

addCommandOrSilentlyFail()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 9
rs 8.8571
cc 5
eloc 5
nc 3
nop 2
1
<?php
2
3
use Symfony\Component\Console\Application as SymfonyApplication;
4
use Symfony\Component\Console\Command\Command as SymfonyCommand;
5
use Symfony\Component\Console\Input\ArrayInput;
6
use Symfony\Component\Console\Input\InputInterface;
7
use Symfony\Component\Console\Input\InputOption;
8
use Symfony\Component\Console\Output\BufferedOutput;
9
use Symfony\Component\Console\Output\OutputInterface;
10
11
/**
12
 * Class Application.
13
 *
14
 * Shameless copy/paste from Taylor Otwell's Laravel
15
 */
16
class SilverstripeApplication extends SymfonyApplication
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
17
{
18
    /**
19
     * The output from the previous command.
20
     *
21
     * @var \Symfony\Component\Console\Output\BufferedOutput
22
     */
23
    protected $lastOutput;
24
25
    public function __construct()
26
    {
27
        parent::__construct();
28
29
        $this->loadCommands();
30
31
        $this->add($default = new DefaultCommand());
32
        $this->setDefaultCommand($default->getName());
33
34
        $this->setAutoExit(false);
35
        $this->setCatchExceptions(false);
36
    }
37
38
    public function run(InputInterface $input = null, OutputInterface $output = null)
39
    {
40
        return parent::run($input, $output);
41
    }
42
43
    /**
44
     * Run an Artisan console command by name.
45
     *
46
     * @param string $command
47
     * @param array  $parameters
48
     *
49
     * @return int
0 ignored issues
show
Documentation introduced by
Should the return type not be null|integer?

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...
50
     */
51
    public function call($command, array $parameters = [])
52
    {
53
        $parameters = array_merge((array) $command, $parameters);
54
55
        $this->lastOutput = new BufferedOutput();
56
57
        $this->setCatchExceptions(false);
58
59
        $result = $this->run(new ArrayInput($parameters), $this->lastOutput);
60
61
        $this->setCatchExceptions(true);
62
63
        return $result;
64
    }
65
66
    /**
67
     * Get the output for the last run command.
68
     *
69
     * @return string
70
     */
71
    public function output()
72
    {
73
        return $this->lastOutput ? $this->lastOutput->fetch() : '';
74
    }
75
76
    /**
77
     * Add a command to the console.
78
     *
79
     * @param \Symfony\Component\Console\Command\Command $command
80
     *
81
     * @return \Symfony\Component\Console\Command\Command
0 ignored issues
show
Documentation introduced by
Should the return type not be SymfonyCommand|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...
82
     */
83
    public function add(SymfonyCommand $command)
84
    {
85
        return $this->addToParent($command);
86
    }
87
88
    /**
89
     * Add the command to the parent instance.
90
     *
91
     * @param \Symfony\Component\Console\Command\Command $command
92
     *
93
     * @return \Symfony\Component\Console\Command\Command
0 ignored issues
show
Documentation introduced by
Should the return type not be SymfonyCommand|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...
94
     */
95
    protected function addToParent(SymfonyCommand $command)
96
    {
97
        return parent::add($command);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (add() instead of addToParent()). Are you sure this is correct? If so, you might want to change this to $this->add().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
98
    }
99
100
    /**
101
     * Get the default input definitions for the applications.
102
     *
103
     * This is used to add the --env option to every available command.
104
     *
105
     * @return \Symfony\Component\Console\Input\InputDefinition
106
     */
107
    protected function getDefaultInputDefinition()
108
    {
109
        $definition = parent::getDefaultInputDefinition();
110
111
        $definition->addOption($this->getEnvironmentOption());
112
113
        return $definition;
114
    }
115
116
    /**
117
     * Get the global environment option for the definition.
118
     *
119
     * @return \Symfony\Component\Console\Input\InputOption
120
     */
121
    protected function getEnvironmentOption()
122
    {
123
        $message = 'The environment the command should run under.';
124
125
        return new InputOption('--env', null, InputOption::VALUE_OPTIONAL, $message);
126
    }
127
128
    /**
129
     * Load all available commands into the console application.
130
     */
131
    protected function loadCommands()
132
    {
133
        /*
134
         * Why does this not work
135
         */
136
        //$commands = ClassInfo::subclassesFor('SilverstripeCommand'); //var_dump($commands);exit();
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
137
138
        $classes = SS_ClassLoader::instance()->getManifest()->getClasses();
139
140
        /** @var SilverstripeCommand $command */
141
        foreach ($classes as $class => $path) {
142
            $this->addCommandOrSilentlyFail($class, $path);
143
        }
144
    }
145
146
    /**
147
     * When developing and renaming or removing a Command, the manifest is not always updated.
148
     *
149
     * We don't want file_not_found or class_does_not_exists error for commands,
150
     * because that prevente running commands like cache:clear etc.
151
     *
152
     * @param string $class
153
     * @param string $path
154
     */
155
    protected function addCommandOrSilentlyFail($class, $path)
156
    {
157
        if(is_file($path) && class_exists($class)) {
158
            $reflection = new ReflectionClass($class);
159
            if (!$reflection->isAbstract() && $reflection->isSubclassOf('SilverstripeCommand')) {
160
                $this->add(new $class());
161
            }
162
        }
163
    }
164
165
}
166