Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / symfony / process / Pipes / AbstractPipes.php
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 = array();
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 = array();
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      * @throws InvalidArgumentException When an input iterator yields a non supported value
92      */
93     protected function write()
94     {
95         if (!isset($this->pipes[0])) {
96             return;
97         }
98         $input = $this->input;
99
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)));
109                     }
110                     $input = (string) $input;
111                 }
112                 $this->inputBuffer = $input;
113                 $this->input->next();
114                 $input = null;
115             } else {
116                 $input = null;
117             }
118         }
119
120         $r = $e = array();
121         $w = array($this->pipes[0]);
122
123         // let's have a look if something changed in streams
124         if (false === @stream_select($r, $w, $e, 0, 0)) {
125             return;
126         }
127
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]);
134                 }
135             }
136
137             if ($input) {
138                 for (;;) {
139                     $data = fread($input, self::CHUNK_SIZE);
140                     if (!isset($data[0])) {
141                         break;
142                     }
143                     $written = fwrite($stdin, $data);
144                     $data = substr($data, $written);
145                     if (isset($data[0])) {
146                         $this->inputBuffer = $data;
147
148                         return array($this->pipes[0]);
149                     }
150                 }
151                 if (feof($input)) {
152                     if ($this->input instanceof \Iterator) {
153                         $this->input->next();
154                     } else {
155                         $this->input = null;
156                     }
157                 }
158             }
159         }
160
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]);
168         }
169     }
170
171     /**
172      * @internal
173      */
174     public function handleError($type, $msg)
175     {
176         $this->lastError = $msg;
177     }
178 }