PluginProbe
UpStream: a Project Management Plugin for WordPress / trunk
UpStream: a Project Management Plugin for WordPress vtrunk
trunk 1.39.0 1.39.1 1.39.2 1.39.3 2.0.7 2.1.0
upstream / vendor / symfony / process / Pipes / AbstractPipes.php

AbstractPipes.php in UpStream: a Project Management Plugin for WordPress trunk, at vendor/symfony/process/Pipes/AbstractPipes.php

183 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 $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($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 /**
45 * {@inheritdoc}
46 */
47 public function close()
48 {
49 foreach ($this->pipes as $pipe) {
50 fclose($pipe);
51 }
52 $this->pipes = [];
53 }
54
55 /**
56 * Returns true if a system call has been interrupted.
57 *
58 * @return bool
59 */
60 protected function hasSystemCallBeenInterrupted()
61 {
62 $lastError = $this->lastError;
63 $this->lastError = null;
64
65 // stream_select returns false when the `select` system call is interrupted by an incoming signal
66 return null !== $lastError && false !== stripos($lastError, 'interrupted system call');
67 }
68
69 /**
70 * Unblocks streams.
71 */
72 protected function unblock()
73 {
74 if (!$this->blocked) {
75 return;
76 }
77
78 foreach ($this->pipes as $pipe) {
79 stream_set_blocking($pipe, 0);
80 }
81 if (\is_resource($this->input)) {
82 stream_set_blocking($this->input, 0);
83 }
84
85 $this->blocked = false;
86 }
87
88 /**
89 * Writes input to stdin.
90 *
91 * @return array|null
92 *
93 * @throws InvalidArgumentException When an input iterator yields a non supported value
94 */
95 protected function write()
96 {
97 if (!isset($this->pipes[0])) {
98 return null;
99 }
100 $input = $this->input;
101
102 if ($input instanceof \Iterator) {
103 if (!$input->valid()) {
104 $input = null;
105 } elseif (\is_resource($input = $input->current())) {
106 stream_set_blocking($input, 0);
107 } elseif (!isset($this->inputBuffer[0])) {
108 if (!\is_string($input)) {
109 if (!is_scalar($input)) {
110 throw new InvalidArgumentException(sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', \get_class($this->input), \gettype($input)));
111 }
112 $input = (string) $input;
113 }
114 $this->inputBuffer = $input;
115 $this->input->next();
116 $input = null;
117 } else {
118 $input = null;
119 }
120 }
121
122 $r = $e = [];
123 $w = [$this->pipes[0]];
124
125 // let's have a look if something changed in streams
126 if (false === @stream_select($r, $w, $e, 0, 0)) {
127 return null;
128 }
129
130 foreach ($w as $stdin) {
131 if (isset($this->inputBuffer[0])) {
132 $written = fwrite($stdin, $this->inputBuffer);
133 $this->inputBuffer = substr($this->inputBuffer, $written);
134 if (isset($this->inputBuffer[0])) {
135 return [$this->pipes[0]];
136 }
137 }
138
139 if ($input) {
140 for (;;) {
141 $data = fread($input, self::CHUNK_SIZE);
142 if (!isset($data[0])) {
143 break;
144 }
145 $written = fwrite($stdin, $data);
146 $data = substr($data, $written);
147 if (isset($data[0])) {
148 $this->inputBuffer = $data;
149
150 return [$this->pipes[0]];
151 }
152 }
153 if (feof($input)) {
154 if ($this->input instanceof \Iterator) {
155 $this->input->next();
156 } else {
157 $this->input = null;
158 }
159 }
160 }
161 }
162
163 // no input to read on resource, buffer is empty
164 if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) {
165 $this->input = null;
166 fclose($this->pipes[0]);
167 unset($this->pipes[0]);
168 } elseif (!$w) {
169 return [$this->pipes[0]];
170 }
171
172 return null;
173 }
174
175 /**
176 * @internal
177 */
178 public function handleError($type, $msg)
179 {
180 $this->lastError = $msg;
181 }
182 }
183