<?php
namespace nur\sery\web\curl;

/**
 * Class curl: wrapper pour curl
 *
 * nécessite l'extension ext-curl
 */
class curl {
  private static function _generic(string $url, ?array $curlOptions=null, ?array &$headers=null): string {
    $curlOptions[CURLOPT_URL] = $url;
    if (!isset($curlOptions[CURLOPT_RETURNTRANSFER])) $curlOptions[CURLOPT_RETURNTRANSFER] = true;
    $extractHeaders = isset($curlOptions[CURLOPT_HEADER]) && $curlOptions[CURLOPT_HEADER];
    $ch = curl_init();
    if ($ch === false) throw new CurlException(null, "init");
    curl_setopt_array($ch, $curlOptions);
    try {
      $result = curl_exec($ch);
      if ($result === false) throw new CurlException($ch);
      if ($extractHeaders) {
        $info = curl_getinfo($ch);
        $headersSize = $info["header_size"];
        $headers = substr($result, 0, $headersSize);
        $headers = explode("\r\n", $headers);
        $result = substr($result, $headersSize);
      }
      return strval($result);
    } finally {
      curl_close($ch);
    }
  }

  static final function get(string $url, ?array $params=null, ?array $curlOptions=null, ?array &$headers=null): string {
    if ($params !== null) {
      $query = http_build_query($params);
      if (strpos($url, "?") !== false) $url = "$url&$query";
      else $url = "$url?$query";
    }
    return self::_generic($url, $curlOptions, $headers);
  }

  private static function _custom(string $method, string $url, ?array $params=null, ?array $curlOptions=null, ?array &$headers=null): string {
    $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
    if ($params !== null) $curlOptions[CURLOPT_POSTFIELDS] = http_build_query($params);
    return self::_generic($url, $curlOptions, $headers);
  }

  static final function post(string $url, ?array $params=null, ?array $curlOptions=null, ?array &$headers=null): string {
    return self::_custom("POST", $url, $params, $curlOptions, $headers);
  }

  static final function put(string $url, ?array $params=null, ?array $curlOptions=null, ?array &$headers=null): string {
    return self::_custom("PUT", $url, $params, $curlOptions, $headers);
  }

  static final function delete(string $url, ?array $params=null, ?array $curlOptions=null, ?array &$headers=null): string {
    return self::_custom("DELETE", $url, $params, $curlOptions, $headers);
  }
}
