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 12namespace Symfony\Component\Process; 13 14use Symfony\Component\Process\Exception\RuntimeException; 15 16/** 17 * Provides a way to continuously write to the input of a Process until the InputStream is closed. 18 * 19 * @author Nicolas Grekas <p@tchwork.com> 20 * 21 * @implements \IteratorAggregate<int, string> 22 */ 23class InputStream implements \IteratorAggregate 24{ 25 /** @var callable|null */ 26 private $onEmpty = null; 27 private $input = []; 28 private $open = true; 29 30 /** 31 * Sets a callback that is called when the write buffer becomes empty. 32 */ 33 public function onEmpty(callable $onEmpty = null) 34 { 35 $this->onEmpty = $onEmpty; 36 } 37 38 /** 39 * Appends an input to the write buffer. 40 * 41 * @param resource|string|int|float|bool|\Traversable|null $input The input to append as scalar, 42 * stream resource or \Traversable 43 */ 44 public function write($input) 45 { 46 if (null === $input) { 47 return; 48 } 49 if ($this->isClosed()) { 50 throw new RuntimeException(sprintf('"%s" is closed.', static::class)); 51 } 52 $this->input[] = ProcessUtils::validateInput(__METHOD__, $input); 53 } 54 55 /** 56 * Closes the write buffer. 57 */ 58 public function close() 59 { 60 $this->open = false; 61 } 62 63 /** 64 * Tells whether the write buffer is closed or not. 65 */ 66 public function isClosed() 67 { 68 return !$this->open; 69 } 70 71 /** 72 * @return \Traversable<int, string> 73 */ 74 #[\ReturnTypeWillChange] 75 public function getIterator() 76 { 77 $this->open = true; 78 79 while ($this->open || $this->input) { 80 if (!$this->input) { 81 yield ''; 82 continue; 83 } 84 $current = array_shift($this->input); 85 86 if ($current instanceof \Iterator) { 87 yield from $current; 88 } else { 89 yield $current; 90 } 91 if (!$this->input && $this->open && null !== $onEmpty = $this->onEmpty) { 92 $this->write($onEmpty($this)); 93 } 94 } 95 } 96} 97