Completed
Pull Request — master (#146)
by Alexander
02:39
created

ProcessUtils::validateInput()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.4444
c 0
b 0
f 0
cc 8
nc 8
nop 2
1
<?php
2
3
/*
4
 * This file was taken from the "symfony/process" for backward compatibility.
5
 * https://github.com/symfony/process/tree/3.2
6
 *
7
 * (c) Alchemy <[email protected]>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
namespace Alchemy\Zippy\ProcessBuilder;
13
use InvalidArgumentException;
14
use Symfony\Component\Process\Process;
15
16
/**
17
 * ProcessUtils is a bunch of utility methods.
18
 *
19
 * This class contains static methods only and is not meant to be instantiated.
20
 *
21
 * @author Martin Hasoň <[email protected]>
22
 */
23
class ProcessUtils
24
{
25
    /**
26
     * This class should not be instantiated.
27
     */
28
    private function __construct()
29
    {
30
    }
31
    /**
32
     * Escapes a string to be used as a shell argument.
33
     *
34
     * @param string $argument The argument that will be escaped
35
     *
36
     * @return string The escaped argument
37
     */
38
    public static function escapeArgument($argument)
39
    {
40
        //Fix for PHP bug #43784 escapeshellarg removes % from given string
41
        //Fix for PHP bug #49446 escapeshellarg doesn't work on Windows
42
        //@see https://bugs.php.net/bug.php?id=43784
43
        //@see https://bugs.php.net/bug.php?id=49446
44
        if ('\\' === DIRECTORY_SEPARATOR) {
45
            if ('' === $argument) {
46
                return escapeshellarg($argument);
47
            }
48
            $escapedArgument = '';
49
            $quote = false;
50
            foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
51
                if ('"' === $part) {
52
                    $escapedArgument .= '\\"';
53
                } elseif (self::isSurroundedBy($part, '%')) {
54
                    // Avoid environment variable expansion
55
                    $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
56
                } else {
57
                    // escape trailing backslash
58
                    if ('\\' === substr($part, -1)) {
59
                        $part .= '\\';
60
                    }
61
                    $quote = true;
62
                    $escapedArgument .= $part;
63
                }
64
            }
65
            if ($quote) {
66
                $escapedArgument = '"'.$escapedArgument.'"';
67
            }
68
            return $escapedArgument;
69
        }
70
        return "'".str_replace("'", "'\\''", $argument)."'";
71
    }
72
    /**
73
     * Validates and normalizes a Process input.
74
     *
75
     * @param string $caller The name of method call that validates the input
76
     * @param mixed  $input  The input to validate
77
     *
78
     * @return mixed The validated input
79
     *
80
     * @throws InvalidArgumentException In case the input is not valid
81
     */
82
    public static function validateInput($caller, $input)
83
    {
84
        if (null !== $input) {
85
            if (is_resource($input)) {
86
                return $input;
87
            }
88
            if (is_string($input)) {
89
                return $input;
90
            }
91
            if (is_scalar($input)) {
92
                return (string) $input;
93
            }
94
            if ($input instanceof Process) {
95
                return $input->getIterator($input::ITER_SKIP_ERR);
96
            }
97
            if ($input instanceof \Iterator) {
98
                return $input;
99
            }
100
            if ($input instanceof \Traversable) {
101
                return new \IteratorIterator($input);
102
            }
103
            throw new InvalidArgumentException(sprintf('%s only accepts strings, Traversable objects or stream resources.', $caller));
104
        }
105
        return $input;
106
    }
107
    private static function isSurroundedBy($arg, $char)
108
    {
109
        return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
110
    }
111
}
112