Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <fabien@symfony.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
 
12
namespace Symfony\Component\Process\Pipes;
13
 
14
use Symfony\Component\Process\Exception\InvalidArgumentException;
15
 
16
/**
17
 * @author Romain Neutron <imprec@gmail.com>
18
 *
19
 * @internal
20
 */
21
abstract class AbstractPipes implements PipesInterface
22
{
23
    public array $pipes = [];
24
 
25
    private $inputBuffer = '';
26
    private $input;
27
    private $blocked = true;
28
    private $lastError;
29
 
30
    /**
31
     * @param resource|string|int|float|bool|\Iterator|null $input
32
     */
33
    public function __construct(mixed $input)
34
    {
35
        if (\is_resource($input) || $input instanceof \Iterator) {
36
            $this->input = $input;
37
        } elseif (\is_string($input)) {
38
            $this->inputBuffer = $input;
39
        } else {
40
            $this->inputBuffer = (string) $input;
41
        }
42
    }
43
 
44
    public function close()
45
    {
46
        foreach ($this->pipes as $pipe) {
47
            if (\is_resource($pipe)) {
48
                fclose($pipe);
49
            }
50
        }
51
        $this->pipes = [];
52
    }
53
 
54
    /**
55
     * Returns true if a system call has been interrupted.
56
     */
57
    protected function hasSystemCallBeenInterrupted(): bool
58
    {
59
        $lastError = $this->lastError;
60
        $this->lastError = null;
61
 
62
        // stream_select returns false when the `select` system call is interrupted by an incoming signal
63
        return null !== $lastError && false !== stripos($lastError, 'interrupted system call');
64
    }
65
 
66
    /**
67
     * Unblocks streams.
68
     */
69
    protected function unblock()
70
    {
71
        if (!$this->blocked) {
72
            return;
73
        }
74
 
75
        foreach ($this->pipes as $pipe) {
76
            stream_set_blocking($pipe, 0);
77
        }
78
        if (\is_resource($this->input)) {
79
            stream_set_blocking($this->input, 0);
80
        }
81
 
82
        $this->blocked = false;
83
    }
84
 
85
    /**
86
     * Writes input to stdin.
87
     *
88
     * @throws InvalidArgumentException When an input iterator yields a non supported value
89
     */
90
    protected function write(): ?array
91
    {
92
        if (!isset($this->pipes[0])) {
93
            return null;
94
        }
95
        $input = $this->input;
96
 
97
        if ($input instanceof \Iterator) {
98
            if (!$input->valid()) {
99
                $input = null;
100
            } elseif (\is_resource($input = $input->current())) {
101
                stream_set_blocking($input, 0);
102
            } elseif (!isset($this->inputBuffer[0])) {
103
                if (!\is_string($input)) {
104
                    if (!\is_scalar($input)) {
105
                        throw new InvalidArgumentException(sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', get_debug_type($this->input), get_debug_type($input)));
106
                    }
107
                    $input = (string) $input;
108
                }
109
                $this->inputBuffer = $input;
110
                $this->input->next();
111
                $input = null;
112
            } else {
113
                $input = null;
114
            }
115
        }
116
 
117
        $r = $e = [];
118
        $w = [$this->pipes[0]];
119
 
120
        // let's have a look if something changed in streams
121
        if (false === @stream_select($r, $w, $e, 0, 0)) {
122
            return null;
123
        }
124
 
125
        foreach ($w as $stdin) {
126
            if (isset($this->inputBuffer[0])) {
127
                $written = fwrite($stdin, $this->inputBuffer);
128
                $this->inputBuffer = substr($this->inputBuffer, $written);
129
                if (isset($this->inputBuffer[0])) {
130
                    return [$this->pipes[0]];
131
                }
132
            }
133
 
134
            if ($input) {
135
                while (true) {
136
                    $data = fread($input, self::CHUNK_SIZE);
137
                    if (!isset($data[0])) {
138
                        break;
139
                    }
140
                    $written = fwrite($stdin, $data);
141
                    $data = substr($data, $written);
142
                    if (isset($data[0])) {
143
                        $this->inputBuffer = $data;
144
 
145
                        return [$this->pipes[0]];
146
                    }
147
                }
148
                if (feof($input)) {
149
                    if ($this->input instanceof \Iterator) {
150
                        $this->input->next();
151
                    } else {
152
                        $this->input = null;
153
                    }
154
                }
155
            }
156
        }
157
 
158
        // no input to read on resource, buffer is empty
159
        if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) {
160
            $this->input = null;
161
            fclose($this->pipes[0]);
162
            unset($this->pipes[0]);
163
        } elseif (!$w) {
164
            return [$this->pipes[0]];
165
        }
166
 
167
        return null;
168
    }
169
 
170
    /**
171
     * @internal
172
     */
173
    public function handleError(int $type, string $msg)
174
    {
175
        $this->lastError = $msg;
176
    }
177
}