Completed
Push — master ( d3a073...5737c8 )
by Greg
02:21
created

src/Robo/Plugin/Commands/ExampleCommands.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Style\SymfonyStyle;
13
14
/**
15
 * Example Robo Plugin Commands.
16
 *
17
 * To create a Robo Plugin, create a standard Composer project. The
18
 * namespace for your commands must end Robo\Plugin\Commands, and
19
 * this suffix must immediately follow some namespace in your composer.json
20
 * file's autoload section.
21
 *
22
 * For example:
23
 *
24
 * "autoload": {
25
 *         "psr-4": {
26
 *             "RoboExample\\": "src"
27
 *         }
28
 *     },
29
 *
30
 * In this instance, the namespace for your plugin commands must be
31
 * RoboExample\Robo\Plugin\Commands.
32
 */
33
class ExampleCommands extends \Robo\Tasks
34
{
35
    /**
36
     * Watch a file.
37
     *
38
     * Demonstrates the 'watch' command. Runs 'composer update' any time
39
     * composer.json changes.
40
     */
41
    public function tryWatch()
42
    {
43
        $this->taskWatch()->monitor(['composer.json', 'composer.lock'], function () {
44
            $this->taskComposerUpdate()->run();
45
        })->run();
46
    }
47
48
    /**
49
     * Demonstrates Robo input APIs.
50
     */
51
    public function tryInput()
52
    {
53
        $this->say('The <b>expression</b> <bogus>is</bogus> <info>a < b</> it even works');
54
        $answer = $this->ask('how are you?');
55
        $this->say('You are '.$answer);
56
        $yes = $this->confirm('Do you want one more question?');
57
        if (!$yes) {
58
            return Result::cancelled();
59
        }
60
        $lang = $this->askDefault('what is your favorite scripting language?', 'PHP');
61
        $this->say($lang);
62
        $pin = $this->askHidden('Ok, now tell your PIN code (it is hidden)');
63
        $this->yell('Ha-ha, your pin code is: '.$pin);
64
        $this->say('Bye!');
65
    }
66
67
    /**
68
     * Demonstrate Robo configuration.
69
     *
70
     * Config values are loaded from the followig locations:
71
     *
72
     *  - [Robo Project]/robo.yml
73
     *  - $HOME/.robo/robo.yml
74
     *  - $CWD/robo.yml
75
     *  - Environment variables ROBO_CONFIG_KEY (e.g. ROBO_OPTIONS_PROGRESS_DELAY)
76
     *  - Overridden on the commandline via -Doptions.progress-delay=value
77
     *
78
     * @param string $key Name of the option to read (e.g. options.progress-delay)
79
     * @option opt An option whose value is printed. Can be overridden in
80
     *   configuration via the configuration key command.try.config.options.opt.
81
     * @option show-all Also print out the value of all configuration options
82
     */
83
    public function tryConfig($key = 'options.progress-delay', $options = ['opt' => '0', 'show-all' => false])
84
    {
85
        $value = \Robo\Robo::config()->get($key);
86
87
        $this->say("The value of $key is " . var_export($value, true));
88
        $this->say("The value of --opt (command.try.config.options.opt) is " . var_export($options['opt'], true));
89
90
        if ($options['show-all']) {
91
            $this->say(var_export(\Robo\Robo::config()->export(), true) . "\n");
92
        }
93
    }
94
95
    /**
96
     * Demonstrates serial execution.
97
     *
98
     * @option $printed Print the output of each process.
99
     * @option $error Include an extra process that fails.
100
     */
101
    public function tryExec($options = ['printed' => true, 'error' => false])
102
    {
103
        $dir = dirname(dirname(dirname(dirname(dirname(__DIR__)))));
104
        $tasks = $this
105
            ->taskExec('php')
106
                ->args(["$dir/tests/_data/parascript.php", "hey", "4"])
107
            ->taskExec('php')
108
                ->args(["$dir/tests/_data/parascript.php", "hoy", "3"])
109
            ->taskExec('php')
110
                ->args(["$dir/tests/_data/parascript.php", "gou", "2"])
111
            ->taskExec('php')
112
                ->args(["$dir/tests/_data/parascript.php", "die", "1"]);
113
        if ($options['error']) {
114
            $tasks->taskExec('ls')->arg("$dir/tests/_data/filenotfound");
115
        }
116
        return $tasks->run();
117
    }
118
119
    /**
120
     * Demonstrates parallel execution.
121
     *
122
     * @option $printed Print the output of each process.
123
     * @option $error Include an extra process that fails.
124
     */
125
    public function tryPara($options = ['printed' => true, 'error' => false])
126
    {
127
        $dir = dirname(dirname(dirname(dirname(dirname(__DIR__)))));
128
        $para = $this->taskParallelExec()
129
            ->printed($options['printed'])
130
            ->process("php $dir/tests/_data/parascript.php hey 4")
131
            ->process("php $dir/tests/_data/parascript.php hoy 3")
132
            ->process("php $dir/tests/_data/parascript.php gou 2")
133
            ->process("php $dir/tests/_data/parascript.php die 1");
134
        if ($options['error']) {
135
            $para->process("ls $dir/tests/_data/filenotfound");
136
        }
137
        return $para->run();
138
    }
139
140
    /**
141
     * try:opt-required
142
     */
143
    public function tryOptRequired($options = ['foo' => InputOption::VALUE_REQUIRED])
144
    {
145
        print "foo is " . $options['foo'];
146
    }
147
148
    /**
149
     * Demonstrates Robo argument passing.
150
     *
151
     * @param string $a The first parameter. Required.
152
     * @param string $b The second parameter. Optional.
153
     */
154
    public function tryArgs($a, $b = 'default')
155
    {
156
        $this->say("The parameter a is $a and b is $b");
157
    }
158
159
    /**
160
     * Demonstrate Robo variable argument passing.
161
     *
162
     * @param array $a A list of commandline parameters.
163
     * @param array $options
164
     */
165
    public function tryArrayArgs(array $a, array $options = ['foo' => []])
166
    {
167
        $this->say("The parameters passed are:\n" . var_export($a, true));
168
        if (!empty($options['foo'])) {
169
            $this->say("The options passed via --foo are:\n" . var_export($options['foo'], true));
170
        }
171
    }
172
173
    /**
174
     * Demonstrate use of SymfonyStyle $io object and Symfony $input object in
175
     * Robo in place of the usual "parameter arguments".
176
     *
177
     * @arg array $a A list of commandline parameters.
178
     * @option foo
179
     * @default a []
180
     * @default foo []
181
     */
182 View Code Duplication
    public function trySymfony(SymfonyStyle $io, InputInterface $input)
183
    {
184
        $io->title('Symfony Style demo');
185
        $a = $input->getArgument('a');
186
        $io->writeln("The parameters passed are:\n" . var_export($a, true));
187
        $foo = $input->getOption('foo');
188
        if (!empty($foo)) {
189
            $this->say("The options passed via --foo are:\n" . var_export($foo, true));
190
        }
191
    }
192
193
    public function tryText()
194
    {
195
        $this->io()->text('This is some text');
196
        $this->io()->text('This is some more text');
197
        $this->io()->text('This is the last text');
198
    }
199
200
    /**
201
     * Demonstrate Robo boolean options.
202
     *
203
     * @param $opts The options.
204
     * @option boolean $silent Supress output.
205
     */
206
    public function tryOptbool($opts = ['silent|s' => false])
207
    {
208
        if (!$opts['silent']) {
209
            $this->say("Hello, world");
210
        }
211
    }
212
213
    /**
214
     * Demonstrate the use of the PHP built-in webserver.
215
     */
216
    public function tryServer()
217
    {
218
        return $this->taskServer(8000)
219
            ->dir('site')
220
            ->arg('site/index.php')
221
            ->run();
222
    }
223
224
    /**
225
     * Demonstrate the use of the Robo open-browser task.
226
     */
227
    public function tryOpenBrowser()
228
    {
229
        return $this->taskOpenBrowser([
230
            'http://robo.li',
231
            'https://github.com/consolidation-org/Robo'
232
            ])->run();
233
    }
234
235
    /**
236
     * Demonstrate Robo error output and command failure.
237
     */
238
    public function tryError()
239
    {
240
        return $this->taskExec('ls xyzzy' . date('U'))->dir('/tmp')->run();
241
    }
242
243
    /**
244
     * Demonstrate Robo standard output and command success.
245
     */
246
    public function trySuccess()
247
    {
248
        return $this->_exec('pwd');
249
    }
250
251
    /**
252
     * @field-labels
253
     *   name: Name
254
     *   species: Species
255
     *   legs: Legs
256
     *   food: Favorite Food
257
     *   id: Id
258
     * @return PropertyList
259
     */
260
    public function tryInfo()
261
    {
262
        $outputData = [
263
            'name' => 'fluffy',
264
            'species' => 'cat',
265
            'legs' => 4,
266
            'food' => 'salmon',
267
            'id' => 389245032,
268
        ];
269
270
        $data = new PropertyList($outputData);
271
272
        // Add a render function to transform cell data when the output
273
        // format is a table, or similar.  This allows us to add color
274
        // information to the output without modifying the data cells when
275
        // using yaml or json output formats.
276
        $data->addRendererFunction(
277
            // n.b. There is a fourth parameter $rowData that may be added here.
278
            function ($key, $cellData, FormatterOptions $options) {
0 ignored issues
show
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...
279
                if ($key == 'name') {
280
                    return "<info>$cellData</>";
281
                }
282
                return $cellData;
283
            }
284
        );
285
286
        return $data;
287
    }
288
289
    /**
290
     * Demonstrate Robo formatters.  Default format is 'table'.
291
     *
292
     * @field-labels
293
     *   first: I
294
     *   second: II
295
     *   third: III
296
     * @default-string-field second
297
     * @usage try:formatters --format=yaml
298
     * @usage try:formatters --format=csv
299
     * @usage try:formatters --fields=first,third
300
     * @usage try:formatters --fields=III,II
301
     * @aliases tf
302
     *
303
     * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
304
     */
305
    public function tryFormatters($somthing = 'default', $options = ['format' => 'table', 'fields' => ''])
0 ignored issues
show
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...
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...
306
    {
307
        $outputData = [
308
            'en' => [ 'first' => 'One',  'second' => 'Two',  'third' => 'Three' ],
309
            'de' => [ 'first' => 'Eins', 'second' => 'Zwei', 'third' => 'Drei'  ],
310
            'jp' => [ 'first' => 'Ichi', 'second' => 'Ni',   'third' => 'San'   ],
311
            'es' => [ 'first' => 'Uno',  'second' => 'Dos',  'third' => 'Tres'  ],
312
        ];
313
        return new RowsOfFields($outputData);
314
    }
315
316
    /**
317
     * Try word wrapping
318
     *
319
     * @field-labels
320
     *   first: First
321
     *   second: Second
322
     *
323
     * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
324
     */
325
    public function tryWrap()
326
    {
327
        $data = [
328
            [
329
                'first' => 'This is a really long cell that contains a lot of data. When it is rendered, it should be wrapped across multiple lines.',
330
                '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.',
331
            ]
332
        ];
333
        return new RowsOfFields($data);
334
    }
335
336
    /**
337
     * Demonstrate an alter hook with an option
338
     *
339
     * @hook alter try:formatters
340
     * @option $french Add a row with French numbers.
341
     * @usage try:formatters --french
342
     */
343
    public function alterFormatters($result, CommandData $commandData)
344
    {
345
        if ($commandData->input()->getOption('french')) {
346
            $result['fr'] = [ 'first' => 'Un',  'second' => 'Deux',  'third' => 'Trois'  ];
347
        }
348
349
        return $result;
350
    }
351
352
    /**
353
     * Demonstrate what happens when a command or a task
354
     * throws an exception.  Note that typically, Robo commands
355
     * should return Result objects rather than throw exceptions.
356
     */
357
    public function tryException($options = ['task' => false])
358
    {
359
        if (!$options['task']) {
360
            throw new RuntimeException('Command failed with an exception.');
361
        }
362
        return new ExceptionTask('Task failed with an exception.');
363
    }
364
365
    /**
366
     * Demonstrate deprecated task behavior.
367
     *
368
     * Demonstrate what happens when using a task that is created via
369
     * direct instantiation, which omits initialization done by the
370
     * container.  Emits a warning message.
371
     */
372
    public function tryDeprecated()
373
    {
374
        // Calling 'new' directly without manually setting
375
        // up dependencies will result in a deprecation warning.
376
        // @see RoboFile::trySuccess()
377
        return (new \Robo\Task\Base\Exec('pwd'))->run();
378
    }
379
380
    /**
381
     * Demonstrate the use of a collection builder to chain multiple tasks
382
     * together into a collection, which is executed once constructed.
383
     *
384
     * For demonstration purposes only; this could, of course, be done
385
     * with a single FilesystemStack.
386
     */
387
    public function tryBuilder()
388
    {
389
        return $this->collectionBuilder()
390
            ->taskFilesystemStack()
391
                ->mkdir('a')
392
                ->touch('a/a.txt')
393
            ->taskFilesystemStack()
394
                ->mkdir('a/b')
395
                ->touch('a/b/b.txt')
396
            ->taskFilesystemStack()
397
                ->mkdir('a/b/c')
398
                ->touch('a/b/c/c.txt')
399
            ->run();
400
    }
401
402
    public function tryState()
403
    {
404
        return $this->collectionBuilder()
405
            ->taskExec('uname -n')
406
                ->printOutput(false)
407
                ->storeState('system-name')
408
            ->taskFilesystemStack()
409
                ->deferTaskConfiguration('mkdir', 'system-name')
410
            ->run();
411
    }
412
413
    public function tryBuilderRollback()
414
    {
415
        // This example will create two builders, and add
416
        // the first one as a child of the second in order
417
        // to demonstrate nested rollbacks.
418
        $collection = $this->collectionBuilder()
419
            ->taskFilesystemStack()
420
                ->mkdir('g')
421
                ->touch('g/g.txt')
422
            ->rollback(
423
                $this->taskDeleteDir('g')
424
            )
425
            ->taskFilesystemStack()
426
                ->mkdir('g/h')
427
                ->touch('g/h/h.txt')
428
            ->taskFilesystemStack()
429
                ->mkdir('g/h/i/c')
430
                ->touch('g/h/i/i.txt');
431
432
        return $this->collectionBuilder()
433
            ->progressMessage('Start recursive collection')
434
            ->addTask($collection)
435
            ->progressMessage('Done with recursive collection')
436
            ->taskExec('ls xyzzy' . date('U'))
437
                ->dir('/tmp')
438
            ->run();
439
    }
440
441
    public function tryWorkdir()
442
    {
443
        // This example works like tryBuilderRollback,
444
        // but does equivalent operations using a working
445
        // directory. The working directory is deleted on rollback
446
        $collection = $this->collectionBuilder();
447
448
        $workdir = $collection->workDir('w');
449
450
        $collection
451
            ->taskFilesystemStack()
452
                ->touch("$workdir/g.txt")
453
            ->taskFilesystemStack()
454
                ->mkdir("$workdir/h")
455
                ->touch("$workdir/h/h.txt")
456
            ->taskFilesystemStack()
457
                ->mkdir("$workdir/h/i/c")
458
                ->touch("$workdir/h/i/i.txt");
459
460
        return $this->collectionBuilder()
461
            ->progressMessage('Start recursive collection')
462
            ->addTask($collection)
463
            ->progressMessage('Done with recursive collection')
464
            ->taskExec('ls xyzzy' . date('U'))
465
                ->dir('/tmp')
466
            ->run();
467
    }
468
469
    /**
470
     * Demonstrates Robo temporary directory usage.
471
     */
472
    public function tryTmpDir()
473
    {
474
        // Set up a collection to add tasks to
475
        $collection = $this->collectionBuilder();
476
477
        // Get a temporary directory to work in. Note that we get a path
478
        // back, but the directory is not created until the task runs.
479
        $tmpPath = $collection->tmpDir();
480
481
        $result = $collection
482
            ->taskWriteToFile("$tmpPath/file.txt")
483
                ->line('Example file')
484
            ->run();
485
486
        if (is_dir($tmpPath)) {
487
            $this->say("The temporary directory at $tmpPath was not cleaned up after the collection completed.");
488
        } else {
489
            $this->say("The temporary directory at $tmpPath was automatically deleted.");
490
        }
491
492
        return $result;
493
    }
494
495
    /**
496
     * Description
497
     * @param $options
498
     * @option delay Miliseconds delay
499
     * @return type
500
     */
501
    public function tryProgress($options = ['delay' => 500])
502
    {
503
        $delay = $options['delay'];
504
        $delayUntilProgressStart = \Robo\Robo::config()->get(\Robo\Config::PROGRESS_BAR_AUTO_DISPLAY_INTERVAL);
505
        $this->say("Progress bar will display after $delayUntilProgressStart seconds of activity.");
506
507
        $processList = range(1, 10);
508
        return $this->collectionBuilder()
509
            ->taskForEach($processList)
510
                ->iterationMessage('Processing {value}')
511
                ->call(
512
                    function ($value) use($delay) {
0 ignored issues
show
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...
513
                        // TaskForEach::call should only be used to do
514
                        // non-Robo operations. To use Robo tasks in an
515
                        // iterator, @see TaskForEach::withBuilder.
516
                        usleep($delay * 1000); // delay units: msec, usleep units: usec
517
                    }
518
                )
519
            ->run();
520
    }
521
522
    public function tryIter()
523
    {
524
        $workdir = 'build/iter-example';
525
        $this->say("Creating sample direcories in $workdir.");
526
527
        $processList = ['cats', 'dogs', 'sheep', 'fish', 'horses', 'cows'];
528
        return $this->collectionBuilder()
529
            ->taskFilesystemStack()
530
                ->mkdir($workdir)
531
            ->taskCleanDir($workdir)
532
            ->taskForEach($processList)
533
                ->withBuilder(
534
                    function ($builder, $key, $value) use ($workdir) {
535
                        return $builder
536
                            ->taskFilesystemStack()
537
                                ->mkdir("$workdir/$value");
538
                    }
539
                )
540
            ->run();
541
    }
542
}
543
544
class ExceptionTask extends \Robo\Task\BaseTask
545
{
546
    protected $message;
547
548
    public function __construct($message)
549
    {
550
        $this->message = $message;
551
    }
552
553
    public function run()
554
    {
555
        throw new RuntimeException($this->message);
556
    }
557
}
558