PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.13.3
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.13.3
3.13.3 3.13.2 3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 All 261 releases
wpfunnels / vendor / symfony / process / Pipes / AbstractPipes.php

AbstractPipes.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.13.3, at vendor/symfony/process/Pipes/AbstractPipes.php

205 lines 6.0 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 <[email protected]>
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 <[email protected]>
18 *
19 * @internal
20 */
21 abstract class AbstractPipes implements PipesInterface
22 {
23 public array $pipes = [];
24
25 private string $inputBuffer = '';
26 /** @var resource|string|\Iterator */
27 private $input;
28 private bool $blocked = true;
29 private ?string $lastError = null;
30
31 /**
32 * @param resource|string|\Iterator $input
33 */
34 public function __construct($input)
35 {
36 if (\is_resource($input) || $input instanceof \Iterator) {
37 $this->input = $input;
38 } else {
39 $this->inputBuffer = (string) $input;
40 }
41 }
42
43 public function close(): void
44 {
45 foreach ($this->pipes as $pipe) {
46 if (\is_resource($pipe)) {
47 fclose($pipe);
48 }
49 }
50 $this->pipes = [];
51 }
52
53 /**
54 * Returns true if a system call has been interrupted.
55 *
56 * stream_select() returns false when the `select` system call is interrupted by an incoming signal.
57 */
58 protected function hasSystemCallBeenInterrupted(): bool
59 {
60 $lastError = $this->lastError;
61 $this->lastError = null;
62
63 if (null === $lastError) {
64 return false;
65 }
66
67 if (false !== stripos($lastError, 'interrupted system call')) {
68 return true;
69 }
70
71 // on applications with a different locale than english, the message above is not found because
72 // it's translated. So we also check for the SOCKET_EINTR constant which is defined under
73 // Windows and UNIX-like platforms (if available on the platform).
74 return \defined('SOCKET_EINTR') && str_starts_with($lastError, 'stream_select(): Unable to select ['.\SOCKET_EINTR.']');
75 }
76
77 /**
78 * Unblocks streams.
79 */
80 protected function unblock(): void
81 {
82 if (!$this->blocked) {
83 return;
84 }
85
86 foreach ($this->pipes as $pipe) {
87 stream_set_blocking($pipe, false);
88 }
89 if (\is_resource($this->input)) {
90 stream_set_blocking($this->input, false);
91 }
92
93 $this->blocked = false;
94 }
95
96 /**
97 * Writes input to stdin.
98 *
99 * @throws InvalidArgumentException When an input iterator yields a non supported value
100 */
101 protected function write(): ?array
102 {
103 if (!isset($this->pipes[0])) {
104 return null;
105 }
106 $input = $this->input;
107
108 if ($input instanceof \Iterator) {
109 if (!$input->valid()) {
110 $input = null;
111 } elseif (\is_resource($input = $input->current())) {
112 stream_set_blocking($input, false);
113 } elseif (!isset($this->inputBuffer[0])) {
114 if (!\is_string($input)) {
115 if (!\is_scalar($input)) {
116 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)));
117 }
118 $input = (string) $input;
119 }
120 $this->inputBuffer = $input;
121 $this->input->next();
122 $input = null;
123 } else {
124 $input = null;
125 }
126 }
127
128 $r = $e = [];
129 $w = [$this->pipes[0]];
130
131 // let's have a look if something changed in streams
132 if (false === @stream_select($r, $w, $e, 0, 0)) {
133 return null;
134 }
135
136 foreach ($w as $stdin) {
137 if (isset($this->inputBuffer[0])) {
138 if (false === $written = @fwrite($stdin, $this->inputBuffer)) {
139 return $this->closeBrokenInputPipe();
140 }
141 $this->inputBuffer = substr($this->inputBuffer, $written);
142 if (isset($this->inputBuffer[0]) && isset($this->pipes[0])) {
143 return [$this->pipes[0]];
144 }
145 }
146
147 if ($input) {
148 while (true) {
149 $data = fread($input, self::CHUNK_SIZE);
150 if (!isset($data[0])) {
151 break;
152 }
153 if (false === $written = @fwrite($stdin, $data)) {
154 return $this->closeBrokenInputPipe();
155 }
156 $data = substr($data, $written);
157 if (isset($data[0])) {
158 $this->inputBuffer = $data;
159
160 return isset($this->pipes[0]) ? [$this->pipes[0]] : null;
161 }
162 }
163 if (feof($input)) {
164 if ($this->input instanceof \Iterator) {
165 $this->input->next();
166 } else {
167 $this->input = null;
168 }
169 }
170 }
171 }
172
173 // no input to read on resource, buffer is empty
174 if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) {
175 $this->input = null;
176 fclose($this->pipes[0]);
177 unset($this->pipes[0]);
178 } elseif (!$w) {
179 return [$this->pipes[0]];
180 }
181
182 return null;
183 }
184
185 private function closeBrokenInputPipe(): void
186 {
187 $this->lastError = error_get_last()['message'] ?? null;
188 if (\is_resource($this->pipes[0] ?? null)) {
189 fclose($this->pipes[0]);
190 }
191 unset($this->pipes[0]);
192
193 $this->input = null;
194 $this->inputBuffer = '';
195 }
196
197 /**
198 * @internal
199 */
200 public function handleError(int $type, string $msg): void
201 {
202 $this->lastError = $msg;
203 }
204 }
205