5 * @package akeebaengine
6 * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
7 * @license GNU General Public License version 3, or later
12 use Akeeba\S3\Exception\PropertyNotFound;
13 use Akeeba\S3\Response\Error;
16 // Protection against direct access
17 defined('AKEEBAENGINE') || die();
20 * Amazon S3 API response object
22 * @property Error $error Response error object
23 * @property string|SimpleXMLElement|null $body Body data
24 * @property int $code Response code
25 * @property array $headers Any headers we may have
34 private $error = null;
39 * @var string|SimpleXMLElement|null
44 * Status code of the response, e.g. 200 for OK, 403 for Forbidden etc
55 private $headers = [];
58 * Response constructor.
60 public function __construct()
62 $this->error = new Error();
66 * Is this an error response?
70 public function isError(): bool
72 return is_null($this->error) || $this->error->isError();
76 * Does this response have a body?
80 public function hasBody(): bool
82 return !empty($this->body);
86 * Get the response error object
90 public function getError(): Error
96 * Set the response error object
100 public function setError(Error $error): void
102 $this->error = $error;
106 * Get the response body
108 * If there is no body set up you get NULL.
110 * If the body is binary data (e.g. downloading a file) or other non-XML data you get a string.
112 * If the body was an XML string – the standard Amazon S3 REST API response type – you get a SimpleXMLElement
115 * @return string|SimpleXMLElement|null
117 public function getBody()
123 * Set the response body. If it's a string we'll try to parse it as XML.
125 * @param string|SimpleXMLElement|null $body
127 public function setBody($body, bool $rawResponse = false): void
138 $this->finaliseBody($rawResponse);
141 public function resetBody(): void
146 public function addToBody(string $data): void
148 if (empty($this->body))
153 $this->body .= $data;
156 public function finaliseBody(bool $rawResponse = false): void
158 if (!$this->hasBody())
163 if (!isset($this->headers['type']))
165 $this->headers['type'] = 'text/plain';
170 && is_string($this->body)
173 ($this->headers['type'] == 'application/xml')
174 || (substr($this->body, 0, 5) == '<?xml')
178 $this->body = simplexml_load_string($this->body);
181 if (is_object($this->body) && ($this->body instanceof SimpleXMLElement))
188 * Returns the status code of the response
192 public function getCode(): int
198 * Sets the status code of the response
202 public function setCode(int $code): void
208 * Get the response headers
212 public function getHeaders(): array
214 return $this->headers;
218 * Set the response headers
220 * @param array $headers
222 public function setHeaders(array $headers): void
224 $this->headers = $headers;
228 * Set a single header
230 * @param string $name The header name
231 * @param string $value The header value
235 public function setHeader(string $name, string $value): void
237 $this->headers[$name] = $value;
241 * Does a header by this name exist?
243 * @param string $name The header to look for
245 * @return bool True if it exists
247 public function hasHeader(string $name): bool
249 return array_key_exists($name, $this->headers);
253 * Unset a response header
255 * @param string $name The header to unset
259 public function unsetHeader(string $name): void
261 if ($this->hasHeader($name))
263 unset ($this->headers[$name]);
268 * Magic getter for the protected properties
270 * @param string $name
274 public function __get(string $name)
279 return $this->getError();
283 return $this->getBody();
287 return $this->getCode();
291 return $this->getHeaders();
295 throw new PropertyNotFound("Property $name not found in " . get_class($this));
299 * Magic setter for the protected properties
301 * @param string $name The name of the property
302 * @param mixed $value The value of the property
306 public function __set(string $name, $value): void
311 $this->setError($value);
315 $this->setBody($value);
319 $this->setCode($value);
323 $this->setHeaders($value);
327 throw new PropertyNotFound("Property $name not found in " . get_class($this));
332 * Scans the SimpleXMLElement body for errors and propagates them to the Error object
334 protected function parseBody(): void
336 if (!in_array($this->code, [200, 204]) &&
337 isset($this->body->Code, $this->body->Message)
340 $this->error = new Error(
342 (string) $this->body->Code . ':' . (string) $this->body->Message
345 if (isset($this->body->Resource))
347 $this->error->setResource((string) $this->body->Resource);