|
|
@@ -1,68 +1,183 @@
|
|
|
<?php
|
|
|
|
|
|
+/**
|
|
|
+ * This file contain fetch class, which is used to communicate with NTFY.sh
|
|
|
+ * REST api. It makes that HTTP request using buildin CURL extension is
|
|
|
+ * much easier, and looks better in high level code.
|
|
|
+ *
|
|
|
+ * @package phpnotify
|
|
|
+ * @author Cixo (Cixo Electronic)
|
|
|
+ */
|
|
|
+namespace phpnotify;
|
|
|
+
|
|
|
+use \TypeError as TypeError;
|
|
|
+use \RuntimeException as RuntimeException;
|
|
|
+
|
|
|
+use \CurlHandle as CurlHandle;
|
|
|
+use \curl_init as curl_init;
|
|
|
+use \curl_setopt as curl_setopt;
|
|
|
+use \curl_close as curl_close;
|
|
|
+use \curl_exec as curl_exec;
|
|
|
+use \curl_error as curl_error;
|
|
|
+use \curl_errno as curl_errno;
|
|
|
+
|
|
|
require('response.php');
|
|
|
|
|
|
+/**
|
|
|
+ * This class is responsible for downloading data from the server. It uses
|
|
|
+ * buildin CURL extension to make HTTP request. It not parsing response
|
|
|
+ * directly, but use {@link response}
|
|
|
+ */
|
|
|
class fetch {
|
|
|
- private bool $has_content;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This store content of the requst body.
|
|
|
+ * @var ?string
|
|
|
+ */
|
|
|
+ private ?string $content;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This store type of content.
|
|
|
+ * @var ?string
|
|
|
+ */
|
|
|
+ private ?string $content_type;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This store method of the request.
|
|
|
+ * @var string
|
|
|
+ */
|
|
|
private string $method;
|
|
|
- private ?string $received;
|
|
|
- private CurlHandle $request;
|
|
|
-
|
|
|
- public function __construct(string $url, string $method = 'GET') {
|
|
|
- $this->received = null;
|
|
|
- $this->has_content = false;
|
|
|
- $this->method = $method;
|
|
|
-
|
|
|
- $this->request = curl_init();
|
|
|
- $this->setopt(CURLOPT_RETURNTRANSFER, true);
|
|
|
- $this->setopt(CURLOPT_FAILONERROR, true);
|
|
|
- $this->setopt(CURLOPT_HEADER, true);
|
|
|
- $this->setopt(CURLOPT_CUSTOMREQUEST, $method);
|
|
|
- $this->setopt(CURLOPT_URL, curl_escape($url));
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This store url to fetch.
|
|
|
+ * @var string
|
|
|
+ */
|
|
|
+ private string $url;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This create new fetch request. It is alias of constructor.
|
|
|
+ *
|
|
|
+ * @link fetch::__construct()
|
|
|
+ * @static
|
|
|
+ * @param string $url URL to fetch.
|
|
|
+ * @return fetch New fetch object.
|
|
|
+ */
|
|
|
+ public static function create(string $url): object {
|
|
|
+ return new self($url);
|
|
|
}
|
|
|
|
|
|
- public function set_json(array $content): object {
|
|
|
- if ($this->has_content) {
|
|
|
- throw new RuntimeException('JSON content already set.');
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * This initialize new fetch request by given URL. Default method for
|
|
|
+ * the request is GET. If do not want to use new, see create.
|
|
|
+ *
|
|
|
+ * @link fetch::create()
|
|
|
+ * @param string $url URL to work with.
|
|
|
+ */
|
|
|
+ public function __construct(string $url) {
|
|
|
+ $this->content = null;
|
|
|
+ $this->content_type = null;
|
|
|
+ $this->method = 'GET';
|
|
|
+ $this->url = $url;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This function could be use send array in the fetch request. Be careful
|
|
|
+ * because this function verify that method of the request is not GET or
|
|
|
+ * HEAD, which can not contain body. Property method must be set before.
|
|
|
+ *
|
|
|
+ * @param array $content Content which must be send.
|
|
|
+ * @return fetch Itself to chain load.
|
|
|
+ */
|
|
|
+ public function send_array(array $content): object {
|
|
|
+ $content = json_encode($content);
|
|
|
+ $type = 'application/json';
|
|
|
|
|
|
+ $this->send_raw($content, $type);
|
|
|
+ return $this;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This function is similar to {@link fetch::send_array()}, but work on
|
|
|
+ * raw string data. Also content type must be set. Be careful, because
|
|
|
+ * it check that method of the request is not GET or HEAD, which can
|
|
|
+ * not contain body content.
|
|
|
+ *
|
|
|
+ * @param string $content Content of the body to send.
|
|
|
+ * @param string $type Type of the content, like "text/plain".
|
|
|
+ * @return fetch Self to chan loading.
|
|
|
+ */
|
|
|
+ public function send_raw(string $content, string $type): object {
|
|
|
if ($this->method === 'GET' or $this->method === 'HEAD') {
|
|
|
- throw new TypeError("JSON request can not be GET or HEAD.");
|
|
|
+ throw new TypeError('GET or HEAD request can not contain body.');
|
|
|
}
|
|
|
|
|
|
- $converted = json_encode($content);
|
|
|
- $headers = [ 'Content-Type: application/json' ];
|
|
|
-
|
|
|
- $this->has_content = true;
|
|
|
- $this->setopt(CURLOPT_POSTFIELDS, $converted);
|
|
|
- $this->setopt(CURLOPT_HTTPHEADER, $headers);
|
|
|
+ $this->content = $content;
|
|
|
+ $this->content_type = $type;
|
|
|
+
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This function set method of the request. Be careful, because it check
|
|
|
+ * that any content is not set, and when content is not null, but trying
|
|
|
+ * to set GET or HEAD method, it throw TypeError.
|
|
|
+ *
|
|
|
+ * @param string $name Name of the method.
|
|
|
+ * @return fetch Self to chain loading.
|
|
|
+ */
|
|
|
+ public function set_method(string $name): object {
|
|
|
+ if ($this->content === null) {
|
|
|
+ $this->method = $name;
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($name === 'GET' || $name === 'HEAD') {
|
|
|
+ throw new TypeError('GET or HEAD request can not contain body.');
|
|
|
+ }
|
|
|
|
|
|
+ $this->method = $name;
|
|
|
return $this;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * That function make request to the server, from fetch config, which
|
|
|
+ * had been config previously. It return response in parsed form, as
|
|
|
+ * instance of response class. Be careful, it raise an RuntimeException
|
|
|
+ * when server does not response correctly.
|
|
|
+ *
|
|
|
+ * @return response Response from the server.
|
|
|
+ */
|
|
|
+ public function request(): response {
|
|
|
+ $request = curl_init($this->url);
|
|
|
+ curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
|
|
|
+ curl_setopt($request, CURLOPT_FAILONERROR, true);
|
|
|
+ curl_setopt($request, CURLOPT_HEADER, true);
|
|
|
+ curl_setopt($request,CURLOPT_CUSTOMREQUEST, $this->method);
|
|
|
|
|
|
- public function request(): string {
|
|
|
- if ($this->received !== null) {
|
|
|
- return $this->received;
|
|
|
+ if ($this->content !== null) {
|
|
|
+ $type = 'Content-Type: '.$this->content_type;
|
|
|
+ $headers = [ $type ];
|
|
|
+
|
|
|
+ curl_setopt($request, CURLOPT_HTTPHEADER, $headers);
|
|
|
+ curl_setopt($request, CURLOPT_POSTFIELDS, $this->content);
|
|
|
}
|
|
|
|
|
|
- $result = curl_exec($this->request);
|
|
|
- $error = curl_error($this->request);
|
|
|
- $error_number = curl_errno($this->request);
|
|
|
+ $result = curl_exec($request);
|
|
|
+ $error = curl_error($request);
|
|
|
+ $error_number = curl_errno($request);
|
|
|
|
|
|
- curl_close($this->received);
|
|
|
+ curl_close($request);
|
|
|
|
|
|
if ($result !== false and $error_number === 0) {
|
|
|
- return $this->received = $result;
|
|
|
+ return new response($result);
|
|
|
}
|
|
|
|
|
|
throw new RuntimeException(
|
|
|
'Can not fetch request. Error code '
|
|
|
- .string($error_number)
|
|
|
+ .strval($error_number)
|
|
|
.': "'.$error.'".'
|
|
|
);
|
|
|
}
|
|
|
-
|
|
|
- private function setopt(int $option, mixed $content): void {
|
|
|
- curl_setopt($this->request, $option, $content);
|
|
|
- }
|
|
|
+
|
|
|
}
|