Completed
Push — master ( cd88c2...2be39e )
by Greg
03:07
created

ExampleCommands::tryBuilderRollback()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 20
nc 1
nop 0
1
<?php
2
namespace RoboExample\Robo\Plugin\Commands;
3
4
use Robo\Result;
5
6
use Consolidation\AnnotatedCommand\CommandData;
7
use Consolidation\OutputFormatters\Options\FormatterOptions;
8
use Consolidation\OutputFormatters\StructuredData\RowsOfFields;
9
use Consolidation\OutputFormatters\StructuredData\PropertyList;
10
use Symfony\Component\Console\Input\InputOption;
11
12
/**
13
 * Example Robo Plugin Commands.
14
 *
15
 * To create a Robo Plugin, create a standard Composer project. The
16
 * namespace for your commands must end Robo\Plugin\Commands, and
17
 * this suffix must immediately follow some namespace in your composer.json
18
 * file's autoload section.
19
 *
20
 * For example:
21
 *
22
 * "autoload": {
23
 *         "psr-4": {
24
 *             "RoboExample\\": "src"
25
 *         }
26
 *     },
27
 *
28
 * In this instance, the namespace for your plugin commands must be
29
 * RoboExample\Robo\Plugin\Commands.
30
 */
31
class ExampleCommands extends \Robo\Tasks
32
{
33
    /**
34
     * Watch a file.
35
     *
36
     * Demonstrates the 'watch' command. Runs 'composer update' any time
37
     * composer.json changes.
38
     */
39
    public function tryWatch()
40
    {
41
        $this->taskWatch()->monitor(['composer.json', 'composer.lock'], function () {
42
            $this->taskComposerUpdate()->run();
43
        })->run();
44
    }
45
46
    /**
47
     * Demonstrates Robo input APIs.
48
     */
49
    public function tryInput()
50
    {
51
        $this->say('The <b>expression</b> <bogus>is</bogus> <info>a < b</> it even works');
52
        $answer = $this->ask('how are you?');
53
        $this->say('You are '.$answer);
54
        $yes = $this->confirm('Do you want one more question?');
55
        if (!$yes) {
56
            return Result::cancelled();
57
        }
58
        $lang = $this->askDefault('what is your favorite scripting language?', 'PHP');
59
        $this->say($lang);
60
        $pin = $this->askHidden('Ok, now tell your PIN code (it is hidden)');
61
        $this->yell('Ha-ha, your pin code is: '.$pin);
62
        $this->say('Bye!');
63
    }
64
65
    /**
66
     * Demonstrates parallel execution.
67
     *
68
     * @option $printed Print the output of each process.
69
     * @option $error Include an extra process that fails.
70
     */
71
    public function tryPara($options = ['printed' => false, 'error' => false])
72
    {
73
        $dir = dirname(__DIR__);
74
        $para = $this->taskParallelExec()
75
            ->printed($options['printed'])
76
            ->process("php $dir/tests/_data/parascript.php hey 4")
77
            ->process("php $dir/tests/_data/parascript.php hoy 3")
78
            ->process("php $dir/tests/_data/parascript.php gou 2")
79
            ->process("php $dir/tests/_data/parascript.php die 1");
80
        if ($options['error']) {
81
            $para->process("ls $dir/tests/_data/filenotfound");
82
        }
83
        return $para->run();
84
    }
85
86
    /**
87
     * try:opt-required
88
     */
89
    public function tryOptRequired($options = ['foo' => InputOption::VALUE_REQUIRED])
90
    {
91
        print "foo is " . $options['foo'];
92
    }
93
94
    /**
95
     * Demonstrates Robo argument passing.
96
     *
97
     * @param string $a The first parameter. Required.
98
     * @param string $b The second parameter. Optional.
99
     */
100
    public function tryArgs($a, $b = 'default')
101
    {
102
        $this->say("The parameter a is $a and b is $b");
103
    }
104
105
    /**
106
     * Demonstrate Robo variable argument passing.
107
     *
108
     * @param $a A list of commandline parameters.
109
     */
110
    public function tryArrayArgs(array $a)
111
    {
112
        $this->say("The parameters passed are:\n" . var_export($a, true));
113
    }
114
115
    /**
116
     * Demonstrate Robo boolean options.
117
     *
118
     * @param $opts The options.
119
     * @option boolean $silent Supress output.
120
     */
121
    public function tryOptbool($opts = ['silent|s' => false])
122
    {
123
        if (!$opts['silent']) {
124
            $this->say("Hello, world");
125
        }
126
    }
127
128
    /**
129
     * Demonstrate the use of the PHP built-in webserver.
130
     */
131
    public function tryServer()
132
    {
133
        return $this->taskServer(8000)
134
            ->dir('site')
135
            ->arg('site/index.php')
136
            ->run();
137
    }
138
139
    /**
140
     * Demonstrate the use of the Robo open-browser task.
141
     */
142
    public function tryOpenBrowser()
143
    {
144
        return $this->taskOpenBrowser([
145
            'http://robo.li',
146
            'https://github.com/consolidation-org/Robo'
147
            ])->run();
148
    }
149
150
    /**
151
     * Demonstrate Robo error output and command failure.
152
     */
153
    public function tryError()
154
    {
155
        return $this->taskExec('ls xyzzy' . date('U'))->dir('/tmp')->run();
156
    }
157
158
    /**
159
     * Demonstrate Robo standard output and command success.
160
     */
161
    public function trySuccess()
162
    {
163
        return $this->_exec('pwd');
164
    }
165
166
    /**
167
     * @field-labels
168
     *   name: Name
169
     *   species: Species
170
     *   legs: Legs
171
     *   food: Favorite Food
172
     *   id: Id
173
     * @return PropertyList
174
     */
175
    public function tryInfo()
176
    {
177
        $outputData = [
178
            'name' => 'fluffy',
179
            'species' => 'cat',
180
            'legs' => 4,
181
            'food' => 'salmon',
182
            'id' => 389245032,
183
        ];
184
185
        $data = new PropertyList($outputData);
186
187
        // Add a render function to transform cell data when the output
188
        // format is a table, or similar.  This allows us to add color
189
        // information to the output without modifying the data cells when
190
        // using yaml or json output formats.
191
        $data->addRendererFunction(
192
            // n.b. There is a fourth parameter $rowData that may be added here.
193
            function ($key, $cellData, FormatterOptions $options) {
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
194
                if ($key == 'name') {
195
                    return "<info>$cellData</>";
196
                }
197
                return $cellData;
198
            }
199
        );
200
201
        return $data;
202
    }
203
204
    /**
205
     * Demonstrate Robo formatters.  Default format is 'table'.
206
     *
207
     * @field-labels
208
     *   first: I
209
     *   second: II
210
     *   third: III
211
     * @default-string-field second
212
     * @usage try:formatters --format=yaml
213
     * @usage try:formatters --format=csv
214
     * @usage try:formatters --fields=first,third
215
     * @usage try:formatters --fields=III,II
216
     * @aliases tf
217
     *
218
     * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
219
     */
220
    public function tryFormatters($somthing = 'default', $options = ['format' => 'table', 'fields' => ''])
0 ignored issues
show
Unused Code introduced by
The parameter $somthing is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
221
    {
222
        $outputData = [
223
            'en' => [ 'first' => 'One',  'second' => 'Two',  'third' => 'Three' ],
224
            'de' => [ 'first' => 'Eins', 'second' => 'Zwei', 'third' => 'Drei'  ],
225
            'jp' => [ 'first' => 'Ichi', 'second' => 'Ni',   'third' => 'San'   ],
226
            'es' => [ 'first' => 'Uno',  'second' => 'Dos',  'third' => 'Tres'  ],
227
        ];
228
        return new RowsOfFields($outputData);
229
    }
230
231
    /**
232
     * Try word wrapping
233
     *
234
     * @field-labels
235
     *   first: First
236
     *   second: Second
237
     *
238
     * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
239
     */
240
    public function tryWrap()
241
    {
242
        $data = [
243
            [
244
                'first' => 'This is a really long cell that contains a lot of data. When it is rendered, it should be wrapped across multiple lines.',
245
                'second' => 'This is the second column of the same table. It is also very long, and should be wrapped across multiple lines, just like the first column.',
246
            ]
247
        ];
248
        return new RowsOfFields($data);
249
    }
250
251
    /**
252
     * Demonstrate an alter hook with an option
253
     *
254
     * @hook alter try:formatters
255
     * @option $french Add a row with French numbers.
256
     * @usage try:formatters --french
257
     */
258
    public function alterFormatters($result, CommandData $commandData)
259
    {
260
        if ($commandData->input()->getOption('french')) {
261
            $result['fr'] = [ 'first' => 'Un',  'second' => 'Deux',  'third' => 'Trois'  ];
262
        }
263
264
        return $result;
265
    }
266
267
    /**
268
     * Demonstrate what happens when a command or a task
269
     * throws an exception.  Note that typically, Robo commands
270
     * should return Result objects rather than throw exceptions.
271
     */
272
    public function tryException($options = ['task' => false])
273
    {
274
        if (!$options['task']) {
275
            throw new RuntimeException('Command failed with an exception.');
276
        }
277
        return new ExceptionTask('Task failed with an exception.');
278
    }
279
280
    /**
281
     * Demonstrate deprecated task behavior.
282
     *
283
     * Demonstrate what happens when using a task that is created via
284
     * direct instantiation, which omits initialization done by the
285
     * container.  Emits a warning message.
286
     */
287
    public function tryDeprecated()
288
    {
289
        // Calling 'new' directly without manually setting
290
        // up dependencies will result in a deprecation warning.
291
        // @see RoboFile::trySuccess()
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
292
        return (new \Robo\Task\Base\Exec('pwd'))->run();
293
    }
294
295
    /**
296
     * Demonstrate the use of a collection builder to chain multiple tasks
297
     * together into a collection, which is executed once constructed.
298
     *
299
     * For demonstration purposes only; this could, of course, be done
300
     * with a single FilesystemStack.
301
     */
302
    public function tryBuilder()
303
    {
304
        return $this->collectionBuilder()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack 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...
305
            ->taskFilesystemStack()
306
                ->mkdir('a')
307
                ->touch('a/a.txt')
308
            ->taskFilesystemStack()
309
                ->mkdir('a/b')
310
                ->touch('a/b/b.txt')
311
            ->taskFilesystemStack()
312
                ->mkdir('a/b/c')
313
                ->touch('a/b/c/c.txt')
314
            ->run();
315
    }
316
317
    public function tryState()
318
    {
319
        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...
320
            ->taskExec('uname -n')
321
                ->printOutput(false)
322
                ->storeState('system-name')
323
            ->taskFilesystemStack()
324
                ->deferTaskConfiguration('mkdir', 'system-name')
325
            ->run();
326
    }
327
328
    public function tryBuilderRollback()
329
    {
330
        // This example will create two builders, and add
331
        // the first one as a child of the second in order
332
        // to demonstrate nested rollbacks.
333
        $collection = $this->collectionBuilder()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack 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...
334
            ->taskFilesystemStack()
335
                ->mkdir('g')
336
                ->touch('g/g.txt')
337
            ->rollback(
338
                $this->taskDeleteDir('g')
339
            )
340
            ->taskFilesystemStack()
341
                ->mkdir('g/h')
342
                ->touch('g/h/h.txt')
343
            ->taskFilesystemStack()
344
                ->mkdir('g/h/i/c')
345
                ->touch('g/h/i/i.txt');
346
347
        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...
348
            ->progressMessage('Start recursive collection')
349
            ->addTask($collection)
350
            ->progressMessage('Done with recursive collection')
351
            ->taskExec('ls xyzzy' . date('U'))
352
                ->dir('/tmp')
353
            ->run();
354
    }
355
356
    public function tryWorkdir()
357
    {
358
        // This example works like tryBuilderRollback,
359
        // but does equivalent operations using a working
360
        // directory. The working directory is deleted on rollback
361
        $collection = $this->collectionBuilder();
362
363
        $workdir = $collection->workDir('w');
364
365
        $collection
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack 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...
366
            ->taskFilesystemStack()
367
                ->touch("$workdir/g.txt")
368
            ->taskFilesystemStack()
369
                ->mkdir("$workdir/h")
370
                ->touch("$workdir/h/h.txt")
371
            ->taskFilesystemStack()
372
                ->mkdir("$workdir/h/i/c")
373
                ->touch("$workdir/h/i/i.txt");
374
375
        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...
376
            ->progressMessage('Start recursive collection')
377
            ->addTask($collection)
378
            ->progressMessage('Done with recursive collection')
379
            ->taskExec('ls xyzzy' . date('U'))
380
                ->dir('/tmp')
381
            ->run();
382
    }
383
384
    /**
385
     * Demonstrates Robo temporary directory usage.
386
     */
387
    public function tryTmpDir()
388
    {
389
        // Set up a collection to add tasks to
390
        $collection = $this->collectionBuilder();
391
392
        // Get a temporary directory to work in. Note that we get a path
393
        // back, but the directory is not created until the task runs.
394
        $tmpPath = $collection->tmpDir();
395
396
        $result = $collection
0 ignored issues
show
Documentation Bug introduced by
The method taskWriteToFile 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...
397
            ->taskWriteToFile("$tmpPath/file.txt")
398
                ->line('Example file')
399
            ->run();
400
401
        if (is_dir($tmpPath)) {
402
            $this->say("The temporary directory at $tmpPath was not cleaned up after the collection completed.");
403
        } else {
404
            $this->say("The temporary directory at $tmpPath was automatically deleted.");
405
        }
406
407
        return $result;
408
    }
409
410
    /**
411
     * Description
412
     * @param $options
413
     * @option delay Miliseconds delay
414
     * @return type
415
     */
416
    public function tryProgress($options = ['delay' => 500])
417
    {
418
        $delay = $options['delay'];
419
        $delayUntilProgressStart = \Robo\Robo::config()->get(\Robo\Config::PROGRESS_BAR_AUTO_DISPLAY_INTERVAL);
420
        $this->say("Progress bar will display after $delayUntilProgressStart seconds of activity.");
421
422
        $processList = range(1, 10);
423
        return $this->collectionBuilder()
0 ignored issues
show
Documentation Bug introduced by
The method taskForEach 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...
424
            ->taskForEach($processList)
425
                ->iterationMessage('Processing {value}')
426
                ->call(
427
                    function ($value) use($delay) {
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
428
                        // TaskForEach::call should only be used to do
429
                        // non-Robo operations. To use Robo tasks in an
430
                        // iterator, @see TaskForEach::withBuilder.
431
                        usleep($delay * 1000); // delay units: msec, usleep units: usec
432
                    }
433
                )
434
            ->run();
435
    }
436
437
    public function tryIter()
438
    {
439
        $workdir = 'build/iter-example';
440
        $this->say("Creating sample direcories in $workdir.");
441
442
        $processList = ['cats', 'dogs', 'sheep', 'fish', 'horses', 'cows'];
443
        return $this->collectionBuilder()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack 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...
444
            ->taskFilesystemStack()
445
                ->mkdir($workdir)
446
            ->taskCleanDir($workdir)
447
            ->taskForEach($processList)
448
                ->withBuilder(
449
                    function ($builder, $key, $value) use ($workdir) {
450
                        return $builder
451
                            ->taskFilesystemStack()
452
                                ->mkdir("$workdir/$value");
453
                    }
454
                )
455
            ->run();
456
    }
457
}
458
459
class ExceptionTask extends \Robo\Task\BaseTask
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
460
{
461
    protected $message;
462
463
    public function __construct($message)
464
    {
465
        $this->message = $message;
466
    }
467
468
    public function run()
469
    {
470
        throw new RuntimeException($this->message);
471
    }
472
}
473