Chris@13: stream = $output->getStream(); Chris@13: $this->cmd = $cmd; Chris@13: } Chris@13: Chris@13: /** Chris@13: * Writes a message to the output. Chris@13: * Chris@13: * @param string $message A message to write to the output Chris@13: * @param bool $newline Whether to add a newline or not Chris@13: * Chris@13: * @throws \RuntimeException When unable to write output (should never happen) Chris@13: */ Chris@13: public function doWrite($message, $newline) Chris@13: { Chris@13: $pipe = $this->getPipe(); Chris@17: if (false === @\fwrite($pipe, $message . ($newline ? PHP_EOL : ''))) { Chris@13: // @codeCoverageIgnoreStart Chris@13: // should never happen Chris@13: throw new \RuntimeException('Unable to write output'); Chris@13: // @codeCoverageIgnoreEnd Chris@13: } Chris@13: Chris@17: \fflush($pipe); Chris@13: } Chris@13: Chris@13: /** Chris@13: * Close the current pager process. Chris@13: */ Chris@13: public function close() Chris@13: { Chris@13: if (isset($this->pipe)) { Chris@17: \fclose($this->pipe); Chris@13: } Chris@13: Chris@13: if (isset($this->proc)) { Chris@17: $exit = \proc_close($this->proc); Chris@13: if ($exit !== 0) { Chris@13: throw new \RuntimeException('Error closing output stream'); Chris@13: } Chris@13: } Chris@13: Chris@13: unset($this->pipe, $this->proc); Chris@13: } Chris@13: Chris@13: /** Chris@13: * Get a pipe for paging output. Chris@13: * Chris@13: * If no active pager process exists, fork one and return its input pipe. Chris@13: */ Chris@13: private function getPipe() Chris@13: { Chris@13: if (!isset($this->pipe) || !isset($this->proc)) { Chris@17: $desc = [['pipe', 'r'], $this->stream, \fopen('php://stderr', 'w')]; Chris@17: $this->proc = \proc_open($this->cmd, $desc, $pipes); Chris@13: Chris@17: if (!\is_resource($this->proc)) { Chris@13: throw new \RuntimeException('Error opening output stream'); Chris@13: } Chris@13: Chris@13: $this->pipe = $pipes[0]; Chris@13: } Chris@13: Chris@13: return $this->pipe; Chris@13: } Chris@13: }