2015-08-17 17:00:26 -07:00
< ? php
/*
* This file is part of the Symfony package .
*
* ( c ) Fabien Potencier < fabien @ symfony . com >
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
namespace Symfony\Component\Process\Pipes ;
/**
* @ author Romain Neutron < imprec @ gmail . com >
*
* @ internal
*/
abstract class AbstractPipes implements PipesInterface
{
/** @var array */
public $pipes = array ();
/** @var string */
2017-02-02 16:28:38 -08:00
private $inputBuffer = '' ;
2015-08-17 17:00:26 -07:00
/** @var resource|null */
2017-02-02 16:28:38 -08:00
private $input ;
2015-08-17 17:00:26 -07:00
/** @var bool */
private $blocked = true ;
2016-04-20 09:56:34 -07:00
public function __construct ( $input )
{
if ( is_resource ( $input )) {
$this -> input = $input ;
} elseif ( is_string ( $input )) {
$this -> inputBuffer = $input ;
} else {
$this -> inputBuffer = ( string ) $input ;
}
}
2015-08-17 17:00:26 -07:00
/**
* { @ inheritdoc }
*/
public function close ()
{
foreach ( $this -> pipes as $pipe ) {
fclose ( $pipe );
}
$this -> pipes = array ();
}
/**
* Returns true if a system call has been interrupted .
*
* @ return bool
*/
protected function hasSystemCallBeenInterrupted ()
{
$lastError = error_get_last ();
// stream_select returns false when the `select` system call is interrupted by an incoming signal
return isset ( $lastError [ 'message' ]) && false !== stripos ( $lastError [ 'message' ], 'interrupted system call' );
}
/**
2015-10-08 11:40:12 -07:00
* Unblocks streams .
2015-08-17 17:00:26 -07:00
*/
protected function unblock ()
{
if ( ! $this -> blocked ) {
return ;
}
foreach ( $this -> pipes as $pipe ) {
stream_set_blocking ( $pipe , 0 );
}
if ( null !== $this -> input ) {
stream_set_blocking ( $this -> input , 0 );
}
$this -> blocked = false ;
}
2016-04-20 09:56:34 -07:00
/**
* Writes input to stdin .
*/
protected function write ()
{
if ( ! isset ( $this -> pipes [ 0 ])) {
return ;
}
2017-02-02 16:28:38 -08:00
$input = $this -> input ;
$r = $e = array ();
2016-04-20 09:56:34 -07:00
$w = array ( $this -> pipes [ 0 ]);
// let's have a look if something changed in streams
if ( false === $n = @ stream_select ( $r , $w , $e , 0 , 0 )) {
return ;
}
foreach ( $w as $stdin ) {
if ( isset ( $this -> inputBuffer [ 0 ])) {
$written = fwrite ( $stdin , $this -> inputBuffer );
$this -> inputBuffer = substr ( $this -> inputBuffer , $written );
if ( isset ( $this -> inputBuffer [ 0 ])) {
return array ( $this -> pipes [ 0 ]);
}
}
2017-02-02 16:28:38 -08:00
if ( $input ) {
2016-04-20 09:56:34 -07:00
for (;;) {
$data = fread ( $input , self :: CHUNK_SIZE );
if ( ! isset ( $data [ 0 ])) {
break ;
}
$written = fwrite ( $stdin , $data );
$data = substr ( $data , $written );
if ( isset ( $data [ 0 ])) {
$this -> inputBuffer = $data ;
return array ( $this -> pipes [ 0 ]);
}
}
2017-02-02 16:28:38 -08:00
if ( feof ( $input )) {
2016-04-20 09:56:34 -07:00
// no more data to read on input resource
// use an empty buffer in the next reads
$this -> input = null ;
}
}
}
// no input to read on resource, buffer is empty
if ( null === $this -> input && ! isset ( $this -> inputBuffer [ 0 ])) {
fclose ( $this -> pipes [ 0 ]);
unset ( $this -> pipes [ 0 ]);
2017-02-02 16:28:38 -08:00
} elseif ( ! $w ) {
2016-04-20 09:56:34 -07:00
return array ( $this -> pipes [ 0 ]);
}
}
2015-08-17 17:00:26 -07:00
}