scratch – Blame information for rev 115

Subversion Repositories:
Rev:
Rev Author Line No. Line
115 office 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 /** @var array */
24 public $pipes = array();
25  
26 /** @var string */
27 private $inputBuffer = '';
28 /** @var resource|scalar|\Iterator|null */
29 private $input;
30 /** @var bool */
31 private $blocked = true;
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 = error_get_last();
63  
64 // stream_select returns false when the `select` system call is interrupted by an incoming signal
65 return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
66 }
67  
68 /**
69 * Unblocks streams.
70 */
71 protected function unblock()
72 {
73 if (!$this->blocked) {
74 return;
75 }
76  
77 foreach ($this->pipes as $pipe) {
78 stream_set_blocking($pipe, 0);
79 }
80 if (is_resource($this->input)) {
81 stream_set_blocking($this->input, 0);
82 }
83  
84 $this->blocked = false;
85 }
86  
87 /**
88 * Writes input to stdin.
89 *
90 * @throws InvalidArgumentException When an input iterator yields a non supported value
91 */
92 protected function write()
93 {
94 if (!isset($this->pipes[0])) {
95 return;
96 }
97 $input = $this->input;
98  
99 if ($input instanceof \Iterator) {
100 if (!$input->valid()) {
101 $input = null;
102 } elseif (is_resource($input = $input->current())) {
103 stream_set_blocking($input, 0);
104 } elseif (!isset($this->inputBuffer[0])) {
105 if (!is_string($input)) {
106 if (!is_scalar($input)) {
107 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)));
108 }
109 $input = (string) $input;
110 }
111 $this->inputBuffer = $input;
112 $this->input->next();
113 $input = null;
114 } else {
115 $input = null;
116 }
117 }
118  
119 $r = $e = array();
120 $w = array($this->pipes[0]);
121  
122 // let's have a look if something changed in streams
123 if (false === $n = @stream_select($r, $w, $e, 0, 0)) {
124 return;
125 }
126  
127 foreach ($w as $stdin) {
128 if (isset($this->inputBuffer[0])) {
129 $written = fwrite($stdin, $this->inputBuffer);
130 $this->inputBuffer = substr($this->inputBuffer, $written);
131 if (isset($this->inputBuffer[0])) {
132 return array($this->pipes[0]);
133 }
134 }
135  
136 if ($input) {
137 for (;;) {
138 $data = fread($input, self::CHUNK_SIZE);
139 if (!isset($data[0])) {
140 break;
141 }
142 $written = fwrite($stdin, $data);
143 $data = substr($data, $written);
144 if (isset($data[0])) {
145 $this->inputBuffer = $data;
146  
147 return array($this->pipes[0]);
148 }
149 }
150 if (feof($input)) {
151 if ($this->input instanceof \Iterator) {
152 $this->input->next();
153 } else {
154 $this->input = null;
155 }
156 }
157 }
158 }
159  
160 // no input to read on resource, buffer is empty
161 if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) {
162 $this->input = null;
163 fclose($this->pipes[0]);
164 unset($this->pipes[0]);
165 } elseif (!$w) {
166 return array($this->pipes[0]);
167 }
168 }
169 }