RoboFileFixture   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 215
Duplicated Lines 4.19 %

Coupling/Cohesion

Components 2
Dependencies 11

Importance

Changes 0
Metric Value
wmc 21
lcom 2
cbo 11
dl 9
loc 215
rs 10
c 0
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A testStyleInjector() 0 9 1
A hookCommandEvent() 0 4 1
A testCommandEvent() 0 4 1
A hookPostCommand() 0 4 1
A testCustomEvent() 0 10 2
A hookOne() 0 4 1
A hookTwo() 0 4 1
A testSimpleList() 0 5 1
A testExec() 0 4 1
A testVerbosityThreshold() 0 17 1
A testSymfony() 9 9 2
A testArrayArgs() 0 4 1
A testSymfonyStyle() 0 9 1
A testError() 0 5 1
A testException() 0 7 2
A testStopOnFail() 0 13 1
A testVerbosity() 0 12 1
A testDeploy() 0 10 1

How to fix   Duplicated Code   

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:

1
<?php
2
3
namespace Robo;
4
5
use Psr\Log\LoggerAwareTrait;
6
use Psr\Log\LoggerAwareInterface;
7
8
use Consolidation\AnnotatedCommand\Events\CustomEventAwareInterface;
9
use Consolidation\AnnotatedCommand\Events\CustomEventAwareTrait;
10
use Consolidation\OutputFormatters\StructuredData\PropertyList;
11
use Robo\Contract\VerbosityThresholdInterface;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Output\OutputInterface;
14
use Symfony\Component\Console\Style\SymfonyStyle;
15
16
/**
17
 * RoboFile under test: a fixture containing some commands to use with tests.
18
 */
19
class RoboFileFixture extends \Robo\Tasks implements LoggerAwareInterface, CustomEventAwareInterface
20
{
21
    use LoggerAwareTrait;
22
    use CustomEventAwareTrait;
23
24
    /**
25
     * Demonstrate Robo variable argument passing.
26
     *
27
     * @param array $a
28
     *   A list of commandline parameters.
29
     */
30
    public function testArrayArgs(array $a)
31
    {
32
        $this->say("The parameters passed are:\n" . var_export($a, true));
33
    }
34
35
    /**
36
     * Demonstrate use of SymfonyStyle
37
     */
38
    public function testSymfonyStyle()
39
    {
40
        $this->io()->title('My Title');
0 ignored issues
show
Deprecated Code introduced by
The method Robo\Common\IO::io() has been deprecated with message: Use a style injector instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
41
        $this->io()->section('Section 1');
0 ignored issues
show
Deprecated Code introduced by
The method Robo\Common\IO::io() has been deprecated with message: Use a style injector instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
42
        $this->io()->text('Some text in section one.');
0 ignored issues
show
Deprecated Code introduced by
The method Robo\Common\IO::io() has been deprecated with message: Use a style injector instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
43
        $this->io()->comment('This is just an example of different styles.');
0 ignored issues
show
Deprecated Code introduced by
The method Robo\Common\IO::io() has been deprecated with message: Use a style injector instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
44
        $this->io()->section('Section 2');
0 ignored issues
show
Deprecated Code introduced by
The method Robo\Common\IO::io() has been deprecated with message: Use a style injector instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
45
        $this->io()->text('Some text in section two.');
0 ignored issues
show
Deprecated Code introduced by
The method Robo\Common\IO::io() has been deprecated with message: Use a style injector instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
46
    }
47
48
    /**
49
     * Demonstrate use of SymfonyStyle with a style injector
50
     */
51
    public function testStyleInjector(SymfonyStyle $io)
52
    {
53
        $io->title('My Title');
54
        $io->section('Section 1');
55
        $io->text('Some text in section one printed via injected io object.');
56
        $io->comment('This is just an example of different styles.');
57
        $io->section('Section 2');
58
        $io->text('Some text in section two.');
59
    }
60
61
    /**
62
     * @hook command-event test:command-event
63
     */
64
    public function hookCommandEvent()
65
    {
66
        $this->io()->text('This is the command-event hook for the test:command-event command.');
0 ignored issues
show
Deprecated Code introduced by
The method Robo\Common\IO::io() has been deprecated with message: Use a style injector instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
67
    }
68
69
    public function testCommandEvent()
70
    {
71
        $this->io()->text('This is the main method for the test:command-event command.');
0 ignored issues
show
Deprecated Code introduced by
The method Robo\Common\IO::io() has been deprecated with message: Use a style injector instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
72
    }
73
74
    /**
75
     * @hook post-command test:command-event
76
     */
77
    public function hookPostCommand()
78
    {
79
        $this->io()->text('This is the post-command hook for the test:command-event command.');
0 ignored issues
show
Deprecated Code introduced by
The method Robo\Common\IO::io() has been deprecated with message: Use a style injector instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
80
    }
81
82
    /**
83
     * This command uses a custom event 'custom-event' to collect data.  Note that
84
     * the event handlers will not be found unless the hook manager is
85
     * injected into this command handler object via `setHookManager()`
86
     * (defined in CustomEventAwareTrait). The Robo DI container does this
87
     * for us through inflection.
88
     *
89
     * @command test:custom-event
90
     */
91
    public function testCustomEvent()
92
    {
93
        $myEventHandlers = $this->getCustomEventHandlers('custom-event');
94
        $result = [];
95
        foreach ($myEventHandlers as $handler) {
96
            $result[] = $handler();
97
        }
98
        sort($result);
99
        return implode(',', $result);
100
    }
101
102
    /**
103
     * @hook on-event custom-event
104
     */
105
    public function hookOne()
106
    {
107
        return 'one';
108
    }
109
110
    /**
111
     * @hook on-event custom-event
112
     */
113
    public function hookTwo()
114
    {
115
        return 'two';
116
    }
117
118
    /**
119
     * Test handling of options
120
     *
121
     * @field-labels
122
     *   a: A
123
     *   b: B
124
     */
125
    public function testSimpleList($options = ['a' => '1', 'b' => '2', 'format' => 'yaml'])
126
    {
127
        $result = ['a' => $options['a'], 'b' => $options['b']];
128
        return new PropertyList($result);
129
    }
130
131
    /**
132
     * Demonstrate Robo error output and command failure.
133
     */
134
    public function testError()
135
    {
136
        $this->io()->text(var_export(\Robo\Robo::config()->export(), true));
0 ignored issues
show
Deprecated Code introduced by
The method Robo\Common\IO::io() has been deprecated with message: Use a style injector instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
137
        return $this->taskExec('ls xyzzy' . date('U'))->dir('/tmp')->run();
0 ignored issues
show
Bug introduced by
The method dir does only exist in Robo\Task\Base\Exec, but not in Robo\Collection\CollectionBuilder.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
138
    }
139
140
    public function testExec()
141
    {
142
        return $this->taskExec('pwd')->run();
143
    }
144
145
    /**
146
     * Demonstrate what happens when a command or a task
147
     * throws an exception.  Note that typically, Robo commands
148
     * should return Result objects rather than throw exceptions.
149
     */
150
    public function testException($options = ['task' => false])
151
    {
152
        if (!$options['task']) {
153
            throw new \RuntimeException('Command failed with an exception.');
154
        }
155
        throw new \RuntimeException('Task failed with an exception.');
156
    }
157
158
    public function testStopOnFail()
159
    {
160
        $this->stopOnFail();
161
        $this->collectionBuilder()
0 ignored issues
show
Documentation Bug introduced by
The method taskExec does not exist on object<Robo\Collection\CollectionBuilder>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
162
            ->taskExec('ls xyzzy' . date('U'))
163
                ->dir('/tmp')
164
            ->run();
165
166
        // stopOnFail() should cause the failed task to throw an exception,
167
        // so we should not get here, and instead exit the program with a
168
        // non-zero status.
169
        return 0;
170
    }
171
172
    public function testVerbosity()
173
    {
174
        $this->output()->writeln('This command will print more information at higher verbosity levels.');
175
        $this->output()->writeln('Try running with -v, -vv or -vvv');
176
        $this->output()->writeln('The current verbosity level is ' . $this->output()->getVerbosity());
177
        $this->output()->writeln('This is a verbose message (-v).', OutputInterface::VERBOSITY_VERBOSE);
178
        $this->output()->writeln('This is a very verbose message (-vv).', OutputInterface::VERBOSITY_VERY_VERBOSE);
179
        $this->output()->writeln('This is a debug message (-vvv).', OutputInterface::VERBOSITY_DEBUG);
180
        $this->logger->warning('This is a warning log message.');
181
        $this->logger->notice('This is a notice log message.');
182
        $this->logger->debug('This is a debug log message.');
183
    }
184
185
    public function testVerbosityThreshold()
186
    {
187
        $this->output()->writeln('This command will print more information at higher verbosity levels.');
188
        $this->output()->writeln('Try running with -v, -vv or -vvv');
189
190
        return $this->collectionBuilder()
0 ignored issues
show
Documentation Bug introduced by
The method taskExec does not exist on object<Robo\Collection\CollectionBuilder>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
191
            ->setVerbosityThreshold(VerbosityThresholdInterface::VERBOSITY_VERBOSE)
192
            ->taskExec('echo verbose or higher')
193
                ->interactive(false)
194
            ->taskExec('echo very verbose or higher')
195
                ->interactive(false)
196
                ->setVerbosityThreshold(VerbosityThresholdInterface::VERBOSITY_VERY_VERBOSE)
197
            ->taskExec('echo always printed')
198
                ->interactive(false)
199
                ->setVerbosityThreshold(VerbosityThresholdInterface::VERBOSITY_NORMAL)
200
            ->run();
201
    }
202
203
    public function testDeploy()
204
    {
205
        $gitTask = $this->taskGitStack()
0 ignored issues
show
Bug introduced by
The method pull does only exist in Robo\Task\Vcs\GitStack, but not in Robo\Collection\CollectionBuilder.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
206
            ->pull();
207
208
        $this->taskSshExec('mysite.com')
0 ignored issues
show
Bug introduced by
The method remoteDir does only exist in Robo\Task\Remote\Ssh, but not in Robo\Collection\CollectionBuilder.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
209
            ->remoteDir('/var/www/somesite')
210
            ->exec($gitTask)
211
            ->run();
212
    }
213
214
    /**
215
     * Demonstrate use of Symfony $input object in Robo in place of
216
     * the usual "parameter arguments".
217
     *
218
     * @param InputInterface $input
219
     * @arg array $a A list of commandline parameters.
220
     * @option foo
221
     * @default a []
222
     * @default foo []
223
     */
224 View Code Duplication
    public function testSymfony(InputInterface $input)
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...
225
    {
226
        $a = $input->getArgument('a');
227
        $this->say("The parameters passed are:\n" . var_export($a, true));
228
        $foo = $input->getOption('foo');
229
        if (!empty($foo)) {
230
            $this->say("The options passed via --foo are:\n" . var_export($foo, true));
231
        }
232
    }
233
}
234