composer package updates
[openemr.git] / vendor / symfony / process / Pipes / AbstractPipes.php
blob9a7d88be896f45fde753bfdd03ddab3e202c65e3
1 <?php
3 /*
4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Process\Pipes;
14 use Symfony\Component\Process\Exception\InvalidArgumentException;
16 /**
17 * @author Romain Neutron <imprec@gmail.com>
19 * @internal
21 abstract class AbstractPipes implements PipesInterface
23 public $pipes = array();
25 private $inputBuffer = '';
26 private $input;
27 private $blocked = true;
28 private $lastError;
30 /**
31 * @param resource|string|int|float|bool|\Iterator|null $input
33 public function __construct($input)
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;
44 /**
45 * {@inheritdoc}
47 public function close()
49 foreach ($this->pipes as $pipe) {
50 fclose($pipe);
52 $this->pipes = array();
55 /**
56 * Returns true if a system call has been interrupted.
58 * @return bool
60 protected function hasSystemCallBeenInterrupted()
62 $lastError = $this->lastError;
63 $this->lastError = null;
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');
69 /**
70 * Unblocks streams.
72 protected function unblock()
74 if (!$this->blocked) {
75 return;
78 foreach ($this->pipes as $pipe) {
79 stream_set_blocking($pipe, 0);
81 if (is_resource($this->input)) {
82 stream_set_blocking($this->input, 0);
85 $this->blocked = false;
88 /**
89 * Writes input to stdin.
91 * @throws InvalidArgumentException When an input iterator yields a non supported value
93 protected function write()
95 if (!isset($this->pipes[0])) {
96 return;
98 $input = $this->input;
100 if ($input instanceof \Iterator) {
101 if (!$input->valid()) {
102 $input = null;
103 } elseif (is_resource($input = $input->current())) {
104 stream_set_blocking($input, 0);
105 } elseif (!isset($this->inputBuffer[0])) {
106 if (!is_string($input)) {
107 if (!is_scalar($input)) {
108 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)));
110 $input = (string) $input;
112 $this->inputBuffer = $input;
113 $this->input->next();
114 $input = null;
115 } else {
116 $input = null;
120 $r = $e = array();
121 $w = array($this->pipes[0]);
123 // let's have a look if something changed in streams
124 if (false === @stream_select($r, $w, $e, 0, 0)) {
125 return;
128 foreach ($w as $stdin) {
129 if (isset($this->inputBuffer[0])) {
130 $written = fwrite($stdin, $this->inputBuffer);
131 $this->inputBuffer = substr($this->inputBuffer, $written);
132 if (isset($this->inputBuffer[0])) {
133 return array($this->pipes[0]);
137 if ($input) {
138 for (;;) {
139 $data = fread($input, self::CHUNK_SIZE);
140 if (!isset($data[0])) {
141 break;
143 $written = fwrite($stdin, $data);
144 $data = substr($data, $written);
145 if (isset($data[0])) {
146 $this->inputBuffer = $data;
148 return array($this->pipes[0]);
151 if (feof($input)) {
152 if ($this->input instanceof \Iterator) {
153 $this->input->next();
154 } else {
155 $this->input = null;
161 // no input to read on resource, buffer is empty
162 if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) {
163 $this->input = null;
164 fclose($this->pipes[0]);
165 unset($this->pipes[0]);
166 } elseif (!$w) {
167 return array($this->pipes[0]);
172 * @internal
174 public function handleError($type, $msg)
176 $this->lastError = $msg;