Passed
Push — main ( e46995...8be666 )
by Siad
08:49
created

ExecTask::findHint()   D

Complexity

Conditions 43
Paths 43

Size

Total Lines 87
Code Lines 83

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 53
CRAP Score 130.2773

Importance

Changes 0
Metric Value
eloc 83
dl 0
loc 87
rs 4.1666
c 0
b 0
f 0
ccs 53
cts 83
cp 0.6385
cc 43
nc 43
nop 1
crap 130.2773

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
 *
16
 * This software consists of voluntary contributions made by many individuals
17
 * and is licensed under the LGPL. For more information please see
18
 * <http://phing.info>.
19
 */
20
21
namespace Phing\Task\System;
22
23
use InvalidArgumentException;
24
use Phing\Exception\BuildException;
25
use Phing\Io\File;
26
use Phing\Io\FileUtils;
27
use Phing\Io\IOException;
28
use Phing\Phing;
29
use Phing\Project;
30
use Phing\Task;
31
use Phing\Task\System\Condition\OsCondition;
32
use Phing\Task\System\Element\LogLevelAware;
33
use Phing\Type\Commandline;
34
use Phing\Type\CommandlineArgument;
35
use Phing\Type\Environment;
36
use Phing\Type\EnvVariable;
37
use Phing\Type\Path;
38
use Phing\Util\StringHelper;
39
40
/**
41
 * Executes a command on the shell.
42
 *
43
 * @author  Andreas Aderhold <[email protected]>
44
 * @author  Hans Lellelid <[email protected]>
45
 * @author  Christian Weiske <[email protected]>
46
 */
47
class ExecTask extends Task
48
{
49
    use LogLevelAware;
50
51
    public const INVALID = PHP_INT_MAX;
52
53
    /**
54
     * Command to be executed.
55
     *
56
     * @var string
57
     */
58
    protected $realCommand;
59
60
    /**
61
     * Commandline managing object.
62
     *
63
     * @var Commandline
64
     */
65
    protected $commandline;
66
67
    /**
68
     * Working directory.
69
     *
70
     * @var File
71
     */
72
    protected $dir;
73
74
    protected $currdir;
75
76
    /**
77
     * Operating system.
78
     *
79
     * @var string
80
     */
81
    protected $os;
82
83
    /**
84
     * Whether to escape shell command using escapeshellcmd().
85
     *
86
     * @var bool
87
     */
88
    protected $escape = false;
89
90
    /**
91
     * Where to direct output.
92
     *
93
     * @var File
94
     */
95
    protected $output;
96
97
    /**
98
     * Whether to use PHP's passthru() function instead of exec().
99
     *
100
     * @var bool
101
     */
102
    protected $passthru = false;
103
104
    /**
105
     * Whether to log returned output as MSG_INFO instead of MSG_VERBOSE.
106
     *
107
     * @var bool
108
     */
109
    protected $logOutput = false;
110
111
    /**
112
     * Where to direct error output.
113
     *
114
     * @var File
115
     */
116
    protected $error;
117
118
    /**
119
     * If spawn is set then [unix] programs will redirect stdout and add '&'.
120
     *
121
     * @var bool
122
     */
123
    protected $spawn = false;
124
125
    /**
126
     * Property name to set with return value from exec call.
127
     *
128
     * @var string
129
     */
130
    protected $returnProperty;
131
132
    /**
133
     * Property name to set with output value from exec call.
134
     *
135
     * @var string
136
     */
137
    protected $outputProperty;
138
139
    /**
140
     * Whether to check the return code.
141
     *
142
     * @var bool
143
     */
144
    protected $checkreturn = false;
145
146
    private $exitValue = self::INVALID;
147
148
    private $osFamily;
149
    private $executable;
150
    private $resolveExecutable = false;
151
    private $searchPath = false;
152
    private $env;
153
154
    /**
155
     * @throws BuildException
156
     */
157 91
    public function __construct()
158
    {
159 91
        parent::__construct();
160 91
        $this->commandline = new Commandline();
161 91
        $this->env = new Environment();
162 91
    }
163
164
    /**
165
     * Main method: wraps execute() command.
166
     *
167
     * @throws BuildException
168
     */
169 36
    public function main()
170
    {
171 36
        if (!$this->isValidOs()) {
172 1
            return null;
173
        }
174
175
        // Suggest Task instead of executable
176 34
        if ($this->executable && ($hint = $this->findHint($this->executable))) {
177 13
            $this->log($hint, Project::MSG_VERBOSE);
178
        }
179
180
        try {
181 34
            $this->commandline->setExecutable($this->resolveExecutable($this->executable, $this->searchPath));
182
        } catch (IOException | \InvalidArgumentException $e) {
183
            throw new BuildException($e);
184
        }
185
186 34
        $this->prepare();
187 32
        $this->buildCommand();
188 32
        [$return, $output] = $this->executeCommand();
189 32
        $this->cleanup($return, $output);
190
191 31
        return $return;
192
    }
193
194
    /**
195
     * @param int $exitValue
196
     *
197
     * @return bool
198
     */
199 1
    public function isFailure($exitValue = null)
200
    {
201 1
        if (null === $exitValue) {
202
            $exitValue = $this->getExitValue();
203
        }
204
205 1
        return 0 !== $exitValue;
206
    }
207
208
    /**
209
     * Query the exit value of the process.
210
     *
211
     * @return int the exit value or self::INVALID if no exit value has
212
     *             been received
213
     */
214
    public function getExitValue(): int
215
    {
216
        return $this->exitValue;
217
    }
218
219
    /**
220
     * The command to use.
221
     *
222
     * @param string $command String or string-compatible (e.g. w/ __toString()).
223
     *
224
     * @throws BuildException
225
     */
226 32
    public function setCommand($command): void
227
    {
228 32
        $this->log(
229 32
            "The command attribute is deprecated.\nPlease use the executable attribute and nested arg elements.",
230 32
            Project::MSG_WARN
231
        );
232 32
        $this->commandline = new Commandline($command);
233 32
        $this->executable = $this->commandline->getExecutable();
234 32
    }
235
236
    /**
237
     * The executable to use.
238
     *
239
     * @param bool|string $value String or string-compatible (e.g. w/ __toString()).
240
     */
241 58
    public function setExecutable($value): void
242
    {
243 58
        if (is_bool($value)) {
244 3
            $value = true === $value ? 'true' : 'false';
245
        }
246 58
        $this->executable = $value;
247 58
        $this->commandline->setExecutable($value);
248 58
    }
249
250
    /**
251
     * Whether to use escapeshellcmd() to escape command.
252
     *
253
     * @param bool $escape If the command shall be escaped or not
254
     */
255 7
    public function setEscape(bool $escape): void
256
    {
257 7
        $this->escape = $escape;
258 7
    }
259
260
    /**
261
     * Specify the working directory for executing this command.
262
     *
263
     * @param File $dir Working directory
264
     */
265 9
    public function setDir(File $dir): void
266
    {
267 9
        $this->dir = $dir;
268 9
    }
269
270
    /**
271
     * Specify OS (or multiple OS) that must match in order to execute this command.
272
     *
273
     * @param string $os Operating system string (e.g. "Linux")
274
     */
275 6
    public function setOs($os): void
276
    {
277 6
        $this->os = (string) $os;
278 6
    }
279
280
    /**
281
     * List of operating systems on which the command may be executed.
282
     */
283
    public function getOs(): string
284
    {
285
        return $this->os;
286
    }
287
288
    /**
289
     * Restrict this execution to a single OS Family.
290
     *
291
     * @param string $osFamily the family to restrict to
292
     */
293 2
    public function setOsFamily($osFamily): void
294
    {
295 2
        $this->osFamily = strtolower($osFamily);
296 2
    }
297
298
    /**
299
     * Restrict this execution to a single OS Family.
300
     */
301
    public function getOsFamily()
302
    {
303
        return $this->osFamily;
304
    }
305
306
    /**
307
     * File to which output should be written.
308
     *
309
     * @param File $f Output log file
310
     */
311 6
    public function setOutput(File $f): void
312
    {
313 6
        $this->output = $f;
314 6
    }
315
316
    /**
317
     * File to which error output should be written.
318
     *
319
     * @param File $f Error log file
320
     */
321 4
    public function setError(File $f): void
322
    {
323 4
        $this->error = $f;
324 4
    }
325
326
    /**
327
     * Whether to use PHP's passthru() function instead of exec().
328
     *
329
     * @param bool $passthru If passthru shall be used
330
     */
331 4
    public function setPassthru($passthru): void
332
    {
333 4
        $this->passthru = $passthru;
334 4
    }
335
336
    /**
337
     * Whether to log returned output as MSG_INFO instead of MSG_VERBOSE.
338
     *
339
     * @param bool $logOutput If output shall be logged visibly
340
     */
341 1
    public function setLogoutput($logOutput): void
342
    {
343 1
        $this->logOutput = $logOutput;
344 1
    }
345
346
    /**
347
     * Whether to suppress all output and run in the background.
348
     *
349
     * @param bool $spawn If the command is to be run in the background
350
     */
351 4
    public function setSpawn($spawn): void
352
    {
353 4
        $this->spawn = $spawn;
354 4
    }
355
356
    /**
357
     * Whether to check the return code.
358
     *
359
     * @param bool $checkreturn If the return code shall be checked
360
     */
361 16
    public function setCheckreturn($checkreturn): void
362
    {
363 16
        $this->checkreturn = $checkreturn;
364 16
    }
365
366
    /**
367
     * The name of property to set to return value from exec() call.
368
     *
369
     * @param string $prop Property name
370
     */
371 5
    public function setReturnProperty($prop): void
372
    {
373 5
        $this->returnProperty = $prop;
374 5
    }
375
376
    /**
377
     * The name of property to set to output value from exec() call.
378
     *
379
     * @param string $prop Property name
380
     */
381 9
    public function setOutputProperty($prop): void
382
    {
383 9
        $this->outputProperty = $prop;
384 9
    }
385
386
    /**
387
     * Add an environment variable to the launched process.
388
     *
389
     * @param EnvVariable $var new environment variable
390
     */
391 3
    public function addEnv(EnvVariable $var)
392
    {
393 3
        $this->env->addVariable($var);
394 3
    }
395
396
    /**
397
     * Creates a nested <arg> tag.
398
     *
399
     * @return CommandlineArgument Argument object
400
     */
401 29
    public function createArg()
402
    {
403 29
        return $this->commandline->createArgument();
404
    }
405
406
    /**
407
     * Set whether to attempt to resolve the executable to a file.
408
     *
409
     * @param bool $resolveExecutable if true, attempt to resolve the
410
     *                                path of the executable
411
     */
412 1
    public function setResolveExecutable($resolveExecutable): void
413
    {
414 1
        $this->resolveExecutable = $resolveExecutable;
415 1
    }
416
417
    /**
418
     * Set whether to search nested, then
419
     * system PATH environment variables for the executable.
420
     *
421
     * @param bool $searchPath if true, search PATHs
422
     */
423 1
    public function setSearchPath($searchPath): void
424
    {
425 1
        $this->searchPath = $searchPath;
426 1
    }
427
428
    /**
429
     * Indicates whether to attempt to resolve the executable to a
430
     * file.
431
     *
432
     * @return bool the resolveExecutable flag
433
     */
434
    public function getResolveExecutable(): bool
435
    {
436
        return $this->resolveExecutable;
437
    }
438
439
    /**
440
     * Prepares the command building and execution, i.e.
441
     * changes to the specified directory.
442
     *
443
     * @throws BuildException
444
     */
445 34
    protected function prepare()
446
    {
447 34
        if (null === $this->dir) {
448 31
            $this->dir = $this->getProject()->getBasedir();
449
        }
450
451 34
        if (null === $this->commandline->getExecutable()) {
0 ignored issues
show
introduced by
The condition null === $this->commandline->getExecutable() is always false.
Loading history...
452 1
            throw new BuildException(
453 1
                'ExecTask: Please provide "executable"'
454
            );
455
        }
456
457
        // expand any symbolic links first
458
        try {
459 33
            if (!$this->dir->getCanonicalFile()->exists()) {
460 1
                throw new BuildException(
461 1
                    "The directory '" . (string) $this->dir . "' does not exist"
462
                );
463
            }
464 32
            if (!$this->dir->getCanonicalFile()->isDirectory()) {
465
                throw new BuildException(
466 32
                    "'" . (string) $this->dir . "' is not a directory"
467
                );
468
            }
469 1
        } catch (IOException $e) {
470
            throw new BuildException(
471
                "'" . (string) $this->dir . "' is not a readable directory"
472
            );
473
        }
474 32
        $this->currdir = getcwd();
475 32
        @chdir($this->dir->getPath());
476
477 32
        $this->commandline->setEscape($this->escape);
478 32
    }
479
480
    /**
481
     * Builds the full command to execute and stores it in $command.
482
     *
483
     * @throws BuildException
484
     *
485
     * @uses   $command
486
     */
487 32
    protected function buildCommand()
488
    {
489 32
        if (null !== $this->error) {
490 1
            $this->realCommand .= ' 2> ' . escapeshellarg($this->error->getPath());
491 1
            $this->log(
492 1
                'Writing error output to: ' . $this->error->getPath(),
493 1
                $this->logLevel
494
            );
495
        }
496
497 32
        if (null !== $this->output) {
498 1
            $this->realCommand .= ' 1> ' . escapeshellarg($this->output->getPath());
499 1
            $this->log(
500 1
                'Writing standard output to: ' . $this->output->getPath(),
501 1
                $this->logLevel
502
            );
503 31
        } elseif ($this->spawn) {
504 1
            $this->realCommand .= ' 1>/dev/null';
505 1
            $this->log('Sending output to /dev/null', $this->logLevel);
506
        }
507
508
        // If neither output nor error are being written to file
509
        // then we'll redirect error to stdout so that we can dump
510
        // it to screen below.
511
512 32
        if (null === $this->output && null === $this->error && false === $this->passthru) {
513 29
            $this->realCommand .= ' 2>&1';
514
        }
515
516
        // we ignore the spawn bool for windows
517 32
        if ($this->spawn) {
518 1
            $this->realCommand .= ' &';
519
        }
520
521 32
        $envString = '';
522 32
        $environment = $this->env->getVariables();
523 32
        if (null !== $environment) {
0 ignored issues
show
introduced by
The condition null !== $environment is always true.
Loading history...
524 3
            foreach ($environment as $variable) {
525 3
                if ($this->isPath($variable)) {
526 1
                    continue;
527
                }
528 2
                $this->log('Setting environment variable: ' . $variable, Project::MSG_VERBOSE);
529 2
                if (OsCondition::isOS(OsCondition::FAMILY_WINDOWS)) {
530
                    $envString .= 'set ' . $variable . '& ';
531
                } else {
532 2
                    $envString .= 'export ' . $variable . '; ';
533
                }
534
            }
535
        }
536
537 32
        $this->realCommand = $envString . $this->commandline . $this->realCommand;
538 32
    }
539
540
    /**
541
     * Executes the command and returns return code and output.
542
     *
543
     * @throws BuildException
544
     *
545
     * @return array array(return code, array with output)
546
     */
547 50
    protected function executeCommand()
548
    {
549 50
        $cmdl = $this->realCommand;
550
551 50
        $this->log('Executing command: ' . $cmdl, $this->logLevel);
552
553 50
        $output = [];
554 50
        $return = null;
555
556 50
        if ($this->passthru) {
557 2
            passthru($cmdl, $return);
558
        } else {
559 48
            exec($cmdl, $output, $return);
560
        }
561
562 50
        return [$return, $output];
563
    }
564
565
    /**
566
     * Runs all tasks after command execution:
567
     * - change working directory back
568
     * - log output
569
     * - verify return value.
570
     *
571
     * @param int   $return Return code
572
     * @param array $output Array with command output
573
     *
574
     * @throws BuildException
575
     */
576 32
    protected function cleanup($return, $output): void
577
    {
578 32
        if (null !== $this->dir) {
579 32
            @chdir($this->currdir);
580
        }
581
582 32
        $outloglevel = $this->logOutput ? Project::MSG_INFO : Project::MSG_VERBOSE;
583 32
        foreach ($output as $line) {
584 25
            $this->log($line, $outloglevel);
585
        }
586
587 32
        $this->maybeSetReturnPropertyValue($return);
588
589 32
        if ($this->outputProperty) {
590 5
            $this->project->setProperty(
591 5
                $this->outputProperty,
592 5
                implode("\n", $output)
593
            );
594
        }
595
596 32
        $this->setExitValue($return);
597
598 32
        if (0 !== $return) {
599 14
            if ($this->checkreturn) {
600 1
                throw new BuildException($this->getTaskType() . ' returned: ' . $return, $this->getLocation());
601
            }
602 13
            $this->log('Result: ' . $return, Project::MSG_ERR);
603
        }
604 31
    }
605
606
    /**
607
     * Set the exit value.
608
     *
609
     * @param int $value exit value of the process
610
     */
611 32
    protected function setExitValue($value): void
612
    {
613 32
        $this->exitValue = $value;
614 32
    }
615
616 50
    protected function maybeSetReturnPropertyValue(int $return)
617
    {
618 50
        if ($this->returnProperty) {
619 3
            $this->getProject()->setNewProperty($this->returnProperty, $return);
620
        }
621 50
    }
622
623
    /**
624
     * Is this the OS the user wanted?
625
     *
626
     * @return bool.
0 ignored issues
show
Documentation Bug introduced by
The doc comment bool. at position 0 could not be parsed: Unknown type name 'bool.' at position 0 in bool..
Loading history...
627
     *               <ul>
628
     *               <li>
629
     *               <li><code>true</code> if the os and osfamily attributes are null.</li>
630
     *               <li><code>true</code> if osfamily is set, and the os family and must match
631
     *               that of the current OS, according to the logic of
632
     *               {@link Os#isOs(String, String, String, String)}, and the result of the
633
     *               <code>os</code> attribute must also evaluate true.
634
     *               </li>
635
     *               <li>
636
     *               <code>true</code> if os is set, and the system.property os.name
637
     *               is found in the os attribute,</li>
638
     *               <li><code>false</code> otherwise.</li>
639
     *               </ul>
640
     */
641 55
    protected function isValidOs(): bool
642
    {
643
        //hand osfamily off to OsCondition class, if set
644 55
        if (null !== $this->osFamily && !OsCondition::isFamily($this->osFamily)) {
645
            return false;
646
        }
647
        //the Exec OS check is different from Os.isOs(), which
648
        //probes for a specific OS. Instead it searches the os field
649
        //for the current os.name
650 54
        $myos = Phing::getProperty('os.name');
651 54
        $this->log('Current OS is ' . $myos, Project::MSG_VERBOSE);
652 54
        if ((null !== $this->os) && (false === strpos($this->os, $myos))) {
653
            // this command will be executed only on the specified OS
654 2
            $this->log(
655 2
                'This OS, ' . $myos
656 2
                . ' was not found in the specified list of valid OSes: ' . $this->os,
657 2
                Project::MSG_VERBOSE
658
            );
659
660 2
            return false;
661
        }
662
663 52
        return true;
664
    }
665
666
    /**
667
     * The method attempts to figure out where the executable is so that we can feed
668
     * the full path. We first try basedir, then the exec dir, and then
669
     * fallback to the straight executable name (i.e. on the path).
670
     *
671
     * @param string $exec           the name of the executable
672
     * @param bool   $mustSearchPath if true, the executable will be looked up in
673
     *                               the PATH environment and the absolute path
674
     *                               is returned
675
     *
676
     * @throws BuildException
677
     * @throws IOException
678
     *
679
     * @return string the executable as a full path if it can be determined
680
     */
681 34
    protected function resolveExecutable($exec, $mustSearchPath): ?string
682
    {
683 34
        if (!$this->resolveExecutable) {
684 33
            return $exec;
685
        }
686
        // try to find the executable
687 1
        $executableFile = $this->getProject()->resolveFile($exec);
688 1
        if ($executableFile->exists()) {
689
            return $executableFile->getAbsolutePath();
690
        }
691
        // now try to resolve against the dir if given
692 1
        if (null !== $this->dir) {
693
            $executableFile = (new FileUtils())->resolveFile($this->dir, $exec);
694
            if ($executableFile->exists()) {
695
                return $executableFile->getAbsolutePath();
696
            }
697
        }
698
        // couldn't find it - must be on path
699 1
        if ($mustSearchPath) {
700 1
            $p = null;
701 1
            $environment = $this->env->getVariables();
702 1
            if (null !== $environment) {
0 ignored issues
show
introduced by
The condition null !== $environment is always true.
Loading history...
703 1
                foreach ($environment as $env) {
704 1
                    if ($this->isPath($env)) {
705 1
                        $p = new Path($this->getProject(), $this->getPath($env));
706
707 1
                        break;
708
                    }
709
                }
710
            }
711 1
            if (null === $p) {
712
                $p = new Path($this->getProject(), getenv('path'));
713
            }
714 1
            if (null !== $p) {
715 1
                $dirs = $p->listPaths();
716 1
                foreach ($dirs as $dir) {
717 1
                    $executableFile = (new FileUtils())->resolveFile(new File($dir), $exec);
718 1
                    if ($executableFile->exists()) {
719 1
                        return $executableFile->getAbsolutePath();
720
                    }
721
                }
722
            }
723
        }
724
725
        return $exec;
726
    }
727
728 3
    private function isPath($line)
729
    {
730 3
        return StringHelper::startsWith('PATH=', $line) || StringHelper::startsWith('Path=', $line);
731
    }
732
733 1
    private function getPath($value)
734
    {
735 1
        if (is_string($value)) {
736 1
            return StringHelper::substring($value, strlen('PATH='));
737
        }
738
739
        if (is_array($value)) {
740
            $p = $value['PATH'];
741
742
            return $p ?? $value['Path'];
743
        }
744
745
        throw new InvalidArgumentException('$value should be of type array or string.');
746
    }
747
748
    /**
749
     * Give a Task as an alternative to executable
750
     */
751 29
    public function findHint(string $executable): ?string
752
    {
753 29
        switch ($executable) {
754 29
            case '/usr/bin/mkdir':
755 29
            case 'mkdir':
756
                $hint = 'Consider using MkdirTask https://www.phing.info/guide/chunkhtml/MkdirTask.html';
757
                break;
758 29
            case '/usr/bin/touch':
759 29
            case 'touch':
760
                $hint = 'Consider using TouchTask https://www.phing.info/guide/chunkhtml/TouchTask.html';
761
                break;
762 29
            case '/usr/bin/truncate':
763 29
            case 'truncate':
764
                $hint = 'Consider using TruncateTask https://www.phing.info/guide/chunkhtml/TruncateTask.html';
765
                break;
766 29
            case '/usr/bin/xsltproc':
767 29
            case 'xsltproc':
768
                $hint = 'Consider using XsltTask https://www.phing.info/guide/chunkhtml/XsltTask.html';
769
                break;
770 29
            case '/usr/bin/chmod':
771 29
            case 'chmod':
772
                $hint = 'Consider using ChmodTask https://www.phing.info/guide/chunkhtml/ChmodTask.html';
773
                break;
774 29
            case '/usr/bin/chown':
775 29
            case 'chown':
776
                $hint = 'Consider using ChownTask https://www.phing.info/guide/chunkhtml/ChownTask.html';
777
                break;
778 29
            case '/usr/bin/mv':
779 29
            case 'mv':
780
                $hint = 'Consider using MoveTask https://www.phing.info/guide/chunkhtml/MoveTask.html';
781
                break;
782 29
            case 'sed':
783
                $hint = 'Consider using ReplaceTokens filter https://www.phing.info/guide/chunkhtml/ReplaceTokens.html';
784
                break;
785 29
            case '/usr/bin/rmdir':
786 29
            case 'rmdir':
787 29
            case '/usr/bin/rm':
788 29
            case 'rm':
789 29
            case '/usr/bin/unlink':
790 29
            case 'unlink':
791
                $hint = 'Consider using DeleteTask https://www.phing.info/guide/chunkhtml/DeleteTask.html';
792
                break;
793 29
            case '/usr/bin/sleep':
794 29
            case 'sleep':
795 1
                $hint = 'Consider using SleepTask https://www.phing.info/guide/chunkhtml/SleepTask.html';
796 1
                break;
797 28
            case '/usr/local/bin':
798 28
            case 'ln':
799
                $hint = 'Consider using SymlinkTask https://www.phing.info/guide/chunkhtml/SymlinkTask.html';
800
                break;
801 28
            case '/usr/bin/wget':
802 28
            case 'wget':
803
                $hint = 'Consider using HttpGetTask https://www.phing.info/guide/chunkhtml/HttpGetTask.html';
804
                break;
805 28
            case '/usr/bin/curl':
806 28
            case 'curl':
807 1
                $hint = 'Consider using HttpRequestTask https://www.phing.info/guide/chunkhtml/HttpRequestTask.html';
808 1
                break;
809 27
            case '/usr/bin/xdg-open':
810 27
            case 'xdg-open':
811 27
            case 'wslview':
812 27
            case 'open':
813 27
            case 'start':
814
                $hint = 'Consider using OpenTask https://www.phing.info/guide/chunkhtml/OpenTask.html';
815
                break;
816 27
            case '/usr/bin/zip':
817 27
            case 'zip':
818
                $hint = 'Consider using ZipTask https://www.phing.info/guide/chunkhtml/ZipTask.html';
819
                break;
820 27
            case '/usr/bin/unzip':
821 27
            case 'unzip':
822
                $hint = 'Consider using UnzipTask https://www.phing.info/guide/chunkhtml/UnzipTask.html';
823
                break;
824 27
            case '/usr/bin/tar':
825 27
            case 'tar':
826
                $hint = 'Consider using TarTask https://www.phing.info/guide/chunkhtml/TarTask.html';
827
                break;
828 27
            case '/usr/bin/echo':
829 27
            case 'echo':
830 11
                $hint = 'Consider using EchoTask https://www.phing.info/guide/chunkhtml/EchoTask.html';
831 11
                break;
832
            default:
833 16
                $hint = null;
834 16
                break;
835
        }
836
837 29
        return $hint;
838
    }
839
}
840