: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @param resource|\CurlHandle $handle cURL handle
* @param string $headers Header string
* @return integer Length of provided header
public function stream_headers($handle, $headers) {
// Why do we do this? cURL will send both the final response and any
// interim responses, such as a 100 Continue. We don't need that.
// (We may want to keep this somewhere just in case)
if ($this->done_headers) {
$this->done_headers = false;
$this->headers .= $headers;
if ($headers === "\r\n") {
$this->done_headers = true;
* Collect data as it's received
* @param resource|\CurlHandle $handle cURL handle
* @param string $data Body data
* @return integer Length of provided data
public function stream_body($handle, $data) {
$this->hooks->dispatch('request.progress', [$data, $this->response_bytes, $this->response_byte_limit]);
$data_length = strlen($data);
// Are we limiting the response size?
if ($this->response_byte_limit) {
if ($this->response_bytes === $this->response_byte_limit) {
// Already at maximum, move on
if (($this->response_bytes + $data_length) > $this->response_byte_limit) {
$limited_length = ($this->response_byte_limit - $this->response_bytes);
$data = substr($data, 0, $limited_length);
if ($this->stream_handle) {
fwrite($this->stream_handle, $data);
$this->response_data .= $data;
$this->response_bytes += strlen($data);
* Format a URL given GET data
* @param string $url Original URL.
* @param array|object $data Data to build query using, see {@link https://www.php.net/http_build_query}
* @return string URL with data
private static function format_get($url, $data) {
$url_parts = parse_url($url);
if (empty($url_parts['query'])) {
$url_parts['query'] = '';
$query = $url_parts['query'];
$query .= '&' . http_build_query($data, '', '&');
$query = trim($query, '&');
if (empty($url_parts['query'])) {
$url = str_replace($url_parts['query'], $query, $url);
* Self-test whether the transport can be used.
* The available capabilities to test for can be found in {@see \WpOrg\Requests\Capability}.
* @param array<string, bool> $capabilities Optional. Associative array of capabilities to test against, i.e. `['<capability>' => true]`.
* @return bool Whether the transport can be used.
public static function test($capabilities = []) {
if (!function_exists('curl_init') || !function_exists('curl_exec')) {
// If needed, check that our installed curl version supports SSL
if (isset($capabilities[Capability::SSL]) && $capabilities[Capability::SSL]) {
$curl_version = curl_version();
if (!(CURL_VERSION_SSL & $curl_version['features'])) {
* Get the correct "Expect" header for the given request data.
* @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD.
* @return string The "Expect" header.
private function get_expect_header($data) {
return strlen((string) $data) >= 1048576 ? '100-Continue' : '';
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($data));
foreach ($iterator as $datum) {
$bytesize += strlen((string) $datum);
if ($bytesize >= 1048576) {