1<?php 2 3namespace iplx\Http; 4 5use Psr\Http\Message\StreamInterface; 6 7trait MessageTrait 8{ 9 /** 10 * Case sensitive header names with lowercase header names as keys 11 * 12 * @var array 13 */ 14 protected $headerNames = []; 15 16 /** 17 * Header values with lowercase header names as keys 18 * 19 * @var array 20 */ 21 protected $headerValues = []; 22 23 /** 24 * The body of this request 25 * 26 * @var StreamInterface 27 */ 28 protected $body; 29 30 /** 31 * Protocol version 32 * 33 * @var string 34 */ 35 protected $protocolVersion; 36 37 public function getProtocolVersion() 38 { 39 return $this->protocolVersion; 40 } 41 42 public function withProtocolVersion($version) 43 { 44 $message = clone $this; 45 $message->protocolVersion = $version; 46 47 return $message; 48 } 49 50 public function getHeaders() 51 { 52 return array_combine($this->headerNames, $this->headerValues); 53 } 54 55 public function hasHeader($header) 56 { 57 return isset($this->headerValues[strtolower($header)]); 58 } 59 60 public function getHeader($header) 61 { 62 $header = strtolower($header); 63 64 if (! isset($this->headerValues[$header])) { 65 return []; 66 } 67 68 return $this->headerValues[$header]; 69 } 70 71 public function getHeaderLine($name) 72 { 73 $name = strtolower($name); 74 75 if (! isset($this->headerValues[$name])) { 76 return ''; 77 } 78 79 return implode(', ', $this->headerValues[$name]); 80 } 81 82 public function withHeader($name, $value) 83 { 84 $name = rtrim($name); 85 86 $value = $this->normalizeHeaderValues($value); 87 88 $normalized = strtolower($name); 89 90 $message = clone $this; 91 $message->headerNames[$normalized] = $name; 92 $message->headerValues[$normalized] = $value; 93 94 return $message; 95 } 96 97 public function withAddedHeader($name, $value) 98 { 99 $name = rtrim($name); 100 101 $value = $this->normalizeHeaderValues($value); 102 103 $normalized = strtolower($name); 104 105 $message = clone $this; 106 if (isset($message->headerNames[$normalized])) { 107 $message->headerValues[$normalized] = array_merge($message->headerValues[$normalized], $value); 108 } else { 109 $message->headerNames[$normalized] = $name; 110 $message->headerValues[$normalized] = $value; 111 } 112 113 return $message; 114 } 115 116 public function withoutHeader($name) 117 { 118 $normalized = strtolower(rtrim($name)); 119 120 $message = clone $this; 121 unset($message->headerNames[$normalized]); 122 unset($message->headerValues[$normalized]); 123 124 return $message; 125 } 126 127 public function getBody() 128 { 129 return $this->body; 130 } 131 132 public function withBody(StreamInterface $body) 133 { 134 $message = clone $this; 135 $message->body = $body; 136 137 return $message; 138 } 139 140 protected function setHeaders(array $headers) 141 { 142 // Prepare header field names and header field values according to 143 // https://tools.ietf.org/html/rfc7230#section-3.2.4 144 $names = array_map('rtrim', array_keys($headers)); 145 $values = $this->normalizeHeaderValues($headers); 146 147 $normalized = array_map('strtolower', $names); 148 149 $this->headerNames = array_combine( 150 $normalized, 151 $names 152 ); 153 154 $this->headerValues = array_combine( 155 $normalized, 156 $values 157 ); 158 } 159 160 protected function normalizeHeaderValues(array $values) 161 { 162 // Prepare header field names and header field values according to 163 // https://tools.ietf.org/html/rfc7230#section-3.2.4 164 return array_map(function ($value) { 165 if (! is_array($value)) { 166 $value = [$value]; 167 } 168 169 return array_map(function ($value) { 170 return trim($value, " \t"); 171 }, $value); 172 }, $values); 173 } 174} 175