AC_services_website_design/system/HTTP/MessageTrait.php

240 lines
6.2 KiB
PHP

<?php
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter\HTTP;
use CodeIgniter\HTTP\Exceptions\HTTPException;
/**
* Message Trait
* Additional methods to make a PSR-7 Message class
* compliant with the framework's own MessageInterface.
*
* @see https://github.com/php-fig/http-message/blob/master/src/MessageInterface.php
*/
trait MessageTrait
{
/**
* List of all HTTP request headers.
*
* @var array<string, Header>
*/
protected $headers = [];
/**
* Holds a map of lower-case header names
* and their normal-case key as it is in $headers.
* Used for case-insensitive header access.
*
* @var array
*/
protected $headerMap = [];
// --------------------------------------------------------------------
// Body
// --------------------------------------------------------------------
/**
* Sets the body of the current message.
*
* @param string $data
*
* @return $this
*/
public function setBody($data): self
{
$this->body = $data;
return $this;
}
/**
* Appends data to the body of the current message.
*
* @param string $data
*
* @return $this
*/
public function appendBody($data): self
{
$this->body .= (string) $data;
return $this;
}
// --------------------------------------------------------------------
// Headers
// --------------------------------------------------------------------
/**
* Populates the $headers array with any headers the server knows about.
*/
public function populateHeaders(): void
{
$contentType = $_SERVER['CONTENT_TYPE'] ?? getenv('CONTENT_TYPE');
if (! empty($contentType)) {
$this->setHeader('Content-Type', $contentType);
}
unset($contentType);
foreach (array_keys($_SERVER) as $key) {
if (sscanf($key, 'HTTP_%s', $header) === 1) {
// take SOME_HEADER and turn it into Some-Header
$header = str_replace('_', ' ', strtolower($header));
$header = str_replace(' ', '-', ucwords($header));
$this->setHeader($header, $_SERVER[$key]);
// Add us to the header map so we can find them case-insensitively
$this->headerMap[strtolower($header)] = $header;
}
}
}
/**
* Returns an array containing all Headers.
*
* @return array<string, Header> An array of the Header objects
*/
public function headers(): array
{
// If no headers are defined, but the user is
// requesting it, then it's likely they want
// it to be populated so do that...
if (empty($this->headers)) {
$this->populateHeaders();
}
return $this->headers;
}
/**
* Returns a single Header object. If multiple headers with the same
* name exist, then will return an array of header objects.
*
* @param string $name
*
* @return array|Header|null
*/
public function header($name)
{
$origName = $this->getHeaderName($name);
return $this->headers[$origName] ?? null;
}
/**
* Sets a header and it's value.
*
* @param array|string|null $value
*
* @return $this
*/
public function setHeader(string $name, $value): self
{
$origName = $this->getHeaderName($name);
if (isset($this->headers[$origName]) && is_array($this->headers[$origName]->getValue())) {
if (! is_array($value)) {
$value = [$value];
}
foreach ($value as $v) {
$this->appendHeader($origName, $v);
}
} else {
$this->headers[$origName] = new Header($origName, $value);
$this->headerMap[strtolower($origName)] = $origName;
}
return $this;
}
/**
* Removes a header from the list of headers we track.
*
* @return $this
*/
public function removeHeader(string $name): self
{
$origName = $this->getHeaderName($name);
unset($this->headers[$origName], $this->headerMap[strtolower($name)]);
return $this;
}
/**
* Adds an additional header value to any headers that accept
* multiple values (i.e. are an array or implement ArrayAccess)
*
* @return $this
*/
public function appendHeader(string $name, ?string $value): self
{
$origName = $this->getHeaderName($name);
array_key_exists($origName, $this->headers)
? $this->headers[$origName]->appendValue($value)
: $this->setHeader($name, $value);
return $this;
}
/**
* Adds an additional header value to any headers that accept
* multiple values (i.e. are an array or implement ArrayAccess)
*
* @return $this
*/
public function prependHeader(string $name, string $value): self
{
$origName = $this->getHeaderName($name);
$this->headers[$origName]->prependValue($value);
return $this;
}
/**
* Takes a header name in any case, and returns the
* normal-case version of the header.
*/
protected function getHeaderName(string $name): string
{
return $this->headerMap[strtolower($name)] ?? $name;
}
/**
* Sets the HTTP protocol version.
*
* @return $this
*
* @throws HTTPException For invalid protocols
*/
public function setProtocolVersion(string $version): self
{
if (! is_numeric($version)) {
$version = substr($version, strpos($version, '/') + 1);
}
// Make sure that version is in the correct format
$version = number_format((float) $version, 1);
if (! in_array($version, $this->validProtocolVersions, true)) {
throw HTTPException::forInvalidHTTPProtocol($version);
}
$this->protocolVersion = $version;
return $this;
}
}