Completed
Pull Request — master (#604)
by Greg
02:48
created

ExampleCommands::tryTmpDir()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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