Emit the HTTP body

@param ResponseInterface $response
@throws \RuntimeException
511408
public function emitBody(ResponseInterface $response)
    {
        $output = $this->createOutputStream();
        
        if (!$output) {
            throw new \RuntimeException("Failed to open output stream");
        }
        
        $response->getBody()->rewind();
        $handle = $response->getBody()->detach();
        
        stream_copy_to_stream($handle, $output);
    }
383773
private function decorateResponse(ResponseInterface $response)
    {
        if ($response instanceof Http\Response) {
            return $response;
        }

        return new Http\Response($this, $response);
    }
629320
public function setBaseResponse(ResponseInterface $response)
    {
        if ($response instanceof GlobalEnvironmentInterface && $response->isStale()) {
            throw new \RuntimeException("Unable to set base response: Response is stale");
        }
        
        $this->baseResponse = $response;
    }
218388
private function sendResponse($response)
    {
        if ($response instanceof ResponseInterface) {
            $response->sendContent();
        } else {
            echo $this->response->send($response);
        }
    }
791872
private function emitHeaders(ResponseInterface $response): void
    {
        /*
        if (headers_sent($file, $line)) {
            throw new \RuntimeException(sprintf('Failed to send headers, because headers have already been sent by "%s" at line %d.', $file, $line));
        }*/
        // headers have already been sent by the developer
        if (headers_sent()) {
            return;
        }

        $statusCode = $response->getStatusCode();

        // TODO : regarder ici pour voir comment on emet les cookies !!!!! https://github.com/zendframework/zend-diactoros/blob/master/src/Response/SapiEmitterTrait.php#L78
        // TODO : regarder ici, car un header peut avoir un tableau de valeurs, dans le cas ou on a mergé 2 headers identiques !!!!   https://github.com/slimphp/Slim/blob/3.x/Slim/App.php#L393
        // headers
        foreach ($response->getHeaders() as $name => $values) {
            $first = stripos($name, 'Set-Cookie') === 0 ? false : true;
            foreach ($values as $value) {
                header(sprintf('%s: %s', $name, $value), $first, $statusCode);
                $first = false;
            }
        }

        // TODO : gérer le cas ou il n'y a pas de ReasonPhrase et mettre une chaine vide : https://github.com/zendframework/zend-diactoros/blob/master/src/Response/SapiEmitterTrait.php#L55
        // Set proper protocol, status code (and reason phrase) header
        /*
        if ($response->getReasonPhrase()) {
            header(sprintf(
                'HTTP/%s %d %s',
                $response->getProtocolVersion(),
                $response->getStatusCode(),
                $response->getReasonPhrase()
            ));
        } else {
            header(sprintf(
                'HTTP/%s %d',
                $response->getProtocolVersion(),
                $response->getStatusCode()
            ));
        }*/

        // It is important to mention that this method should be called after the headers are sent, in order to prevent PHP from changing the status code of the emitted response.
        header(sprintf('HTTP/%s %d %s', $response->getProtocolVersion(), $statusCode, $response->getReasonPhrase()), true, $statusCode);

        // cookies
//TODO : utiliser les cookies comme des "headers" classiques ('Set-Cookies:xxxxxxx')
//https://github.com/paragonie/PHP-Cookie/blob/master/src/Cookie.php#L358

//        foreach ($response->getCookies() as $cookie) {
//          setrawcookie($cookie['name'], $cookie['value'], $cookie['expire'], $cookie['path'], $cookie['domain'], $cookie['secure'], $cookie['httponly']);
//        }

//        flush();
//      }

      // cookies
      /*
      foreach ($this->headers->getCookies() as $cookie) {
          if ($cookie->isRaw()) {
              setrawcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
          } else {
              setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
          }
      }*/
    }
317390
protected function emitBody(ResponseInterface $response, int $bufferSize){
        if(1 > $bufferSize){
            throw new \InvalidArgumentException();
        }

        //  NO Content と Not Modified はボディが必要ない
        if(in_array($response->getStatusCode(), [204, 304])){
            return;
        }

        $body   = $response->getBody();

        //  シークできるならバッファサイズに合わせてリードする
        if($body->isSeekable()){
            $body->rewind();
            while(!$body->eof()){
                echo $body->read($bufferSize);
            }
        }else{
            echo $body->getContents();
        }
    }
876774
public function dispatch(RequestInterface $request, ResponseInterface $response = null)
    {
        if (!($request instanceof ConsoleRequest)) {
            throw new \RuntimeException('You can use this controller only from a console!');
        }

        return parent::dispatch($request, $response);
    }
386601
public function emit(Response $response, $maxBufferLength = 8192)
    {
        $this->assertNoPreviousOutput();

        $this->emitHeaders($response);
        $this->emitStatusLine($response);
        
        if ($response->hasCallback()) {
            call_user_func($response->getCallback());
        } elseif ($response->hasHeader('Accept-Ranges')) {
            $range = $this->parseContentRange($response->getHeaderLine('Content-Range'));
            if (is_array($range) && $range[0] === 'bytes') {
                $this->emitBodyRange($range, $response, $maxBufferLength);
            } else {
                $body = $response->getBody();
                if ($body->isSeekable()) {
                    $body->rewind();
                }
                if (!$body->isReadable()) {
                    echo $body;
                } else {
                    while (!$body->eof()) {
                        echo $body->read($maxBufferLength);
                    }
                }
            }
        } else {
            echo $response->getBody();
        }
    }
647099
private function withHTML(ResponseInterface $response, array $context)
    {
        $rendered = $this->template->render($context);

        return $this
            ->withNewBody($response, $rendered)
            ->withHeader('Content-Type', 'text/html');
    }
428919
public function emitHeaders(ResponseInterface $response)
    {
        foreach ($response->getHeaders() as $name => $values) {
            foreach (array_values((array)$values) as $i => $value) {
                $this->header("$name: $value", $i === 0);
            }
        }
    }
884714
public function emit(ResponseInterface $response)
    {
        $code = $response->code() . ' ' . $response->reason();

        $headers = $response->headers();

        $version = $response->version();

        foreach ($headers as $name => $values)
        {
            header($name . ': ' . implode(',', $values));
        }

        header(sprintf('HTTP/%s %s', $version, $code));

        return $response;
    }
1306307
public function processResponse(ResponseInterface $response, SystemEvent $event)
    {
        if ($event->getName() === SystemEvent::FINISH) {
            $event->stopPropagation(true);
            $server  = $this->getServer();
            $emitter = $server->getEmitter();
            $emitter->emit($response);

            return;
        }
        $events = $this->getEvents();
        $event->setResult(SystemEvent::FINISH, $response);
        $events->trigger($event(SystemEvent::FINISH));
    }
1012111
private function processHttpOkResponse(ResponseInterface $response)
    {
        $body = $this->getBodyAsArray($response);

        if (isset($body['error'])) {
            $response = $this->processHttpOkResponseWithError($body);
        } else {
            $response = $this->processHttpOkResponseWithoutError($body);
        }

        return $response;
    }
121692
public function sendResponseBody(ResponseInterface $response):void
    {
        if (($body = $response->getBody()->detach()) === null) {
            $body = $response->getBody()->__toString();
        }
        $this->sendBody($body);
    }
1247273
public function handleResponse(ServerRequestInterface $request, ResponseInterface $response)
    {
        $applicationEvent = $this->getApplicationEvent();
        $applicationEvent->setName(self::EVENT_RESPONSE_CREATED);
        $applicationEvent->setResponse($this->getRouter()->dispatch(
            $request,
            $response
        ));

        $this->emit($applicationEvent, $request, $response);

        return $applicationEvent->getResponse();
    }
121867
public function sendHeaders(ResponseInterface $response): self
    {
        // headers have already been sent by the developer
        if (headers_sent()) {
            return $this;
        }

        $headers = $response->getHeaders();
        if (!isset($headers['date'])) {
            $date = new DateTime();
            $date->setTimezone(new \DateTimeZone('UTC'));
            $headers['date'][] = $date->format('D, d M Y H:i:s').' GMT';
        }
        $statusCode = $response->getStatusCode();

        // headers
        foreach ($headers as $name => $values) {
            foreach ($values as $value) {
                header($name.': '.$value, false, $statusCode);
            }
        }

        // status
        header(sprintf('HTTP/%s %s %s', $response->getProtocolVersion(), $statusCode, $response->getReasonPhrase()), true, $statusCode);

        // todo: cookies

        return $this;
    }
2886
public function emit(ResponseInterface $response, EmitterInterface $emitter = null)
    {
        if (!$emitter) {
            $emitter = new ResponseEmitter();
        }
        $emitter->emit($response);
    }