Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\Process; Chris@0: Chris@0: use Symfony\Component\Process\Exception\RuntimeException; Chris@0: Chris@0: /** Chris@0: * Provides a way to continuously write to the input of a Process until the InputStream is closed. Chris@0: * Chris@0: * @author Nicolas Grekas Chris@0: */ Chris@0: class InputStream implements \IteratorAggregate Chris@0: { Chris@17: /** @var callable|null */ Chris@0: private $onEmpty = null; Chris@17: private $input = []; Chris@0: private $open = true; Chris@0: Chris@0: /** Chris@0: * Sets a callback that is called when the write buffer becomes empty. Chris@0: */ Chris@0: public function onEmpty(callable $onEmpty = null) Chris@0: { Chris@0: $this->onEmpty = $onEmpty; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Appends an input to the write buffer. Chris@0: * Chris@17: * @param resource|string|int|float|bool|\Traversable|null $input The input to append as scalar, Chris@17: * stream resource or \Traversable Chris@0: */ Chris@0: public function write($input) Chris@0: { Chris@0: if (null === $input) { Chris@0: return; Chris@0: } Chris@0: if ($this->isClosed()) { Chris@0: throw new RuntimeException(sprintf('%s is closed', static::class)); Chris@0: } Chris@0: $this->input[] = ProcessUtils::validateInput(__METHOD__, $input); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Closes the write buffer. Chris@0: */ Chris@0: public function close() Chris@0: { Chris@0: $this->open = false; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tells whether the write buffer is closed or not. Chris@0: */ Chris@0: public function isClosed() Chris@0: { Chris@0: return !$this->open; Chris@0: } Chris@0: Chris@0: public function getIterator() Chris@0: { Chris@0: $this->open = true; Chris@0: Chris@0: while ($this->open || $this->input) { Chris@0: if (!$this->input) { Chris@0: yield ''; Chris@0: continue; Chris@0: } Chris@0: $current = array_shift($this->input); Chris@0: Chris@0: if ($current instanceof \Iterator) { Chris@0: foreach ($current as $cur) { Chris@0: yield $cur; Chris@0: } Chris@0: } else { Chris@0: yield $current; Chris@0: } Chris@0: if (!$this->input && $this->open && null !== $onEmpty = $this->onEmpty) { Chris@0: $this->write($onEmpty($this)); Chris@0: } Chris@0: } Chris@0: } Chris@0: }