TaskCommand::execute()   C
last analyzed

Complexity

Conditions 11
Paths 60

Size

Total Lines 34
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 132

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 34
ccs 0
cts 32
cp 0
rs 5.2653
cc 11
eloc 22
nc 60
nop 2
crap 132

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @author Gerard van Helden <[email protected]>
4
 * @copyright Zicht Online <http://zicht.nl>
5
 */
6
7
namespace Zicht\Tool\Command;
8
9
use Symfony\Component\Console\Input\InputOption;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Output;
12
use Symfony\Component\Console\Input\InputArgument;
13
use Symfony\Component\Console\Application;
14
use Zicht\Tool\PluginTaskListenerInterface;
15
16
/**
17
 * Command to execute a specific task
18
 */
19
class TaskCommand extends BaseCommand
20
{
21
    protected $taskName;
22
    protected $flags;
23
    protected $opts;
24
    protected $taskReference;
25
26
    /**
27
     * Construct the front end command for the specified task name.
28
     *
29
     * @param null|string $name
30
     * @param array $arguments
31
     * @param array $options
32
     * @param array $flags
33
     * @param string $help
34
     */
35
    public function __construct($name, $arguments, $options, $flags, $help)
36
    {
37
        $this->taskReference = array_merge(array('tasks'), explode('.', $name));
38
        $this->taskName = str_replace(array('.', '_'), array(':', '-'), $name);
39
40
        parent::__construct($this->taskName);
41
42
        $this->flags = $flags;
43
        $this->opts = $options;
44
45
46
        // first line of help is the description
47
        $this->setDescription(preg_replace('/^([^\n]*).*/s', '$1', $help));
48
        $this->setHelp(trim($help));
49
50
        foreach ($arguments as $name => $required) {
51
            $mode = $required ? InputArgument::REQUIRED : InputArgument::OPTIONAL;
52
53
            if ($multiple = ('[]' === substr($name, -2))) {
0 ignored issues
show
Unused Code introduced by
$multiple is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
54
                $name = substr($name, 0, -2);
55
                $mode |= InputArgument::IS_ARRAY;
56
            }
57
58
            $this->addArgument($name, $mode);
59
        }
60
        foreach ($options as $name) {
61
            $this
62
                ->addOption($this->varToName($name), '', InputOption::VALUE_REQUIRED)
63
            ;
64
        }
65
        foreach ($flags as $name => $value) {
66
            $name = $this->varToName($name);
67
            $this
68
                ->addOption($name, '', InputOption::VALUE_NONE)
69
                ->addOption('no-' . $name, '', InputOption::VALUE_NONE)
70
            ;
71
        }
72
    }
73
74
    /**
75
     * Sets the application instance for this command.
76
     *
77
     * @param Application $application An Application instance
78
     */
79
    public function setApplication(Application $application = null)
80
    {
81
        parent::setApplication($application);
82
83
        if (!is_null($application)) {
84
            try {
85
                foreach($this->getContainer()->plugins as $plugin) {
86
                    if ($plugin instanceof PluginTaskListenerInterface) {
87
                        $name = implode('.', array_slice($this->getTaskReference(), 1));
88
                        $listeners = $plugin->getTaskListeners();
89
                        if (in_array($name, array_keys($listeners))) {
90
                            call_user_func_array(array($plugin, $listeners[$name]), array($this));
91
                        }
92
                    }
93
                }
94
            } catch (\UnexpectedValueException $e) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
95
        }
96
97
    }
98
99
    /**
100
     * @{@inheritDoc}
101
     */
102
    public function addOption($name, $shortcut = null, $mode = null, $help = null, $default = null)
103
    {
104
        $helpTag = ($mode === InputOption::VALUE_NONE) ? "--$name" : "--$name=" . strtoupper($name);
105
        return parent::addOption($name, $shortcut, $mode, $help ?: $this->parseHelp($helpTag), $default);
106
    }
107
108
    /**
109
     * @{@inheritDoc}
110
     */
111
    public function addArgument($name, $mode = null, $help = null, $default = null)
112
    {
113
        return parent::addArgument($name, $mode, $help ?: $this->parseHelp($name), $default);
114
    }
115
116
    /**
117
     * will add the given option the opt stack so it will resolved for the z plugin.
118
     *
119
     * @param string $name
120
     * @param null $shortcut
121
     * @param null $mode
122
     * @param null $help
123
     * @param null $default
124
     * @return $this
125
     */
126
    public function addResolvableOption($name, $shortcut = null, $mode = null, $help = null, $default = null)
127
    {
128
        $this->opts[] = $name;
129
        return parent::addOption($name, $shortcut, $mode, $help, $default);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (addOption() instead of addResolvableOption()). Are you sure this is correct? If so, you might want to change this to $this->addOption().

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...
130
    }
131
132
    private function parseHelp($name)
133
    {
134
        $ret = '';
135
        $this->setHelp(
136
            preg_replace_callback(
137
                sprintf('/\s*%s: (.*)(\n|$)/', $name),
138
                function ($m) use (&$ret) {
139
                    $ret = trim($m[1]);
140
                    return '';
141
                },
142
                $this->getHelp()
143
            )
144
        );
145
        return $ret;
146
    }
147
148
149
    protected function varToName($name)
150
    {
151
        return str_replace('_', '-', $name);
152
    }
153
154
155
    /**
156
     * @param string $name
157
     *
158
     * @return string
159
     */
160
    protected function nameToVar($name)
161
    {
162
        return str_replace('-', '_', $name);
163
    }
164
165
166
    /**
167
     * @{inheritDoc}
168
     */
169
    public function getSynopsis($short = false)
170
    {
171
        $ret = parent::getSynopsis($short);
172
173
        foreach ($this->flags as $name => $value) {
174
            $i = 0;
175
            $ret = preg_replace_callback(
176
                '/\[--(no-)?' . $name . '\]/',
177
                function () use(&$i, $name) {
178
                    if ($i++ == 0) {
179
                        return '[--[no|]-' . $name . ']';
180
                    }
181
                    return '';
182
                },
183
                $ret
184
            );
185
        }
186
187
        return $ret;
188
    }
189
190
191
    /**
192
     * Adds the default '--explain', '--force', '--plugin' and '--debug' options
193
     *
194
     * @return void
195
     */
196
    protected function configure()
197
    {
198
        $this
199
            ->addOption('explain', '', InputOption::VALUE_NONE, 'Explains the commands that would be executed.')
200
            ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force execution of otherwise skipped tasks.')
201
            ->addOption('plugin', '', InputOption::VALUE_REQUIRED, 'Load additional plugins on-the-fly')
202
            ->addOption('debug', '', InputOption::VALUE_NONE, "Set the debug flag")
203
        ;
204
    }
205
206
207
    /**
208
     * Executes the specified task
209
     *
210
     * @param \Symfony\Component\Console\Input\InputInterface $input
211
     * @param \Symfony\Component\Console\Output\OutputInterface $output
212
     * @return mixed
213
     */
214
    protected function execute(InputInterface $input, Output\OutputInterface $output)
215
    {
216
        foreach ($this->getDefinition()->getArguments() as $arg) {
217
            if ($arg->getName() === 'command') {
218
                continue;
219
            }
220
            if ($input->getArgument($arg->getName())) {
221
                $this->getContainer()->set(explode('.', $this->nameToVar($arg->getName())), $input->getArgument($arg->getName()));
222
            }
223
        }
224
        foreach ($this->opts as $opt) {
225
            $optName = $this->varToName($opt);
226
            if ($input->getOption($optName)) {
227
                $this->getContainer()->set(explode('.', $optName), $input->getOption($optName));
228
            }
229
        }
230
        foreach ($this->flags as $name => $value) {
231
            $varName = explode('.', $name);
232
            $optName = $this->varToName($name);
233
            $this->getContainer()->set($varName, $value);
234
235
            if ($input->getOption('no-' . $optName) && $input->getOption($optName)) {
236
                throw new \InvalidArgumentException("Conflicting options --no-{$optName} and --{$optName} supplied. That confuses me.");
237
            }
238
            if ($input->getOption('no-' . $optName)) {
239
                $this->getContainer()->set($varName, false);
240
            } elseif ($input->getOption($optName)) {
241
                $this->getContainer()->set($varName, true);
242
            }
243
        }
244
245
        $callable = $this->getContainer()->get($this->getTaskReference());
246
        call_user_func($callable, $this->getContainer());
247
    }
248
249
    /**
250
     * Returns the reference path that points to the task declaration in the container.
251
     *
252
     * @return string
253
     */
254
    protected function getTaskReference()
255
    {
256
        return $this->taskReference;
257
    }
258
}
259