Chris@0: expand($template, $variables); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Debug function used to describe the provided value type and class. Chris@0: * Chris@0: * @param mixed $input Chris@0: * Chris@0: * @return string Returns a string containing the type of the variable and Chris@0: * if a class is provided, the class name. Chris@0: */ Chris@0: function describe_type($input) Chris@0: { Chris@0: switch (gettype($input)) { Chris@0: case 'object': Chris@0: return 'object(' . get_class($input) . ')'; Chris@0: case 'array': Chris@0: return 'array(' . count($input) . ')'; Chris@0: default: Chris@0: ob_start(); Chris@0: var_dump($input); Chris@0: // normalize float vs double Chris@0: return str_replace('double(', 'float(', rtrim(ob_get_clean())); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Parses an array of header lines into an associative array of headers. Chris@0: * Chris@0: * @param array $lines Header lines array of strings in the following Chris@0: * format: "Name: Value" Chris@0: * @return array Chris@0: */ Chris@0: function headers_from_lines($lines) Chris@0: { Chris@0: $headers = []; Chris@0: Chris@0: foreach ($lines as $line) { Chris@0: $parts = explode(':', $line, 2); Chris@0: $headers[trim($parts[0])][] = isset($parts[1]) Chris@0: ? trim($parts[1]) Chris@0: : null; Chris@0: } Chris@0: Chris@0: return $headers; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns a debug stream based on the provided variable. Chris@0: * Chris@0: * @param mixed $value Optional value Chris@0: * Chris@0: * @return resource Chris@0: */ Chris@0: function debug_resource($value = null) Chris@0: { Chris@0: if (is_resource($value)) { Chris@0: return $value; Chris@0: } elseif (defined('STDOUT')) { Chris@0: return STDOUT; Chris@0: } Chris@0: Chris@0: return fopen('php://output', 'w'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Chooses and creates a default handler to use based on the environment. Chris@0: * Chris@0: * The returned handler is not wrapped by any default middlewares. Chris@0: * Chris@0: * @throws \RuntimeException if no viable Handler is available. Chris@0: * @return callable Returns the best handler for the given system. Chris@0: */ Chris@0: function choose_handler() Chris@0: { Chris@0: $handler = null; Chris@0: if (function_exists('curl_multi_exec') && function_exists('curl_exec')) { Chris@0: $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler()); Chris@0: } elseif (function_exists('curl_exec')) { Chris@0: $handler = new CurlHandler(); Chris@0: } elseif (function_exists('curl_multi_exec')) { Chris@0: $handler = new CurlMultiHandler(); Chris@0: } Chris@0: Chris@0: if (ini_get('allow_url_fopen')) { Chris@0: $handler = $handler Chris@0: ? Proxy::wrapStreaming($handler, new StreamHandler()) Chris@0: : new StreamHandler(); Chris@0: } elseif (!$handler) { Chris@0: throw new \RuntimeException('GuzzleHttp requires cURL, the ' Chris@0: . 'allow_url_fopen ini setting, or a custom HTTP handler.'); Chris@0: } Chris@0: Chris@0: return $handler; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the default User-Agent string to use with Guzzle Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: function default_user_agent() Chris@0: { Chris@0: static $defaultAgent = ''; Chris@0: Chris@0: if (!$defaultAgent) { Chris@0: $defaultAgent = 'GuzzleHttp/' . Client::VERSION; Chris@0: if (extension_loaded('curl') && function_exists('curl_version')) { Chris@0: $defaultAgent .= ' curl/' . \curl_version()['version']; Chris@0: } Chris@0: $defaultAgent .= ' PHP/' . PHP_VERSION; Chris@0: } Chris@0: Chris@0: return $defaultAgent; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns the default cacert bundle for the current system. Chris@0: * Chris@0: * First, the openssl.cafile and curl.cainfo php.ini settings are checked. Chris@0: * If those settings are not configured, then the common locations for Chris@0: * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X Chris@0: * and Windows are checked. If any of these file locations are found on Chris@0: * disk, they will be utilized. Chris@0: * Chris@0: * Note: the result of this function is cached for subsequent calls. Chris@0: * Chris@0: * @return string Chris@0: * @throws \RuntimeException if no bundle can be found. Chris@0: */ Chris@0: function default_ca_bundle() Chris@0: { Chris@0: static $cached = null; Chris@0: static $cafiles = [ Chris@0: // Red Hat, CentOS, Fedora (provided by the ca-certificates package) Chris@0: '/etc/pki/tls/certs/ca-bundle.crt', Chris@0: // Ubuntu, Debian (provided by the ca-certificates package) Chris@0: '/etc/ssl/certs/ca-certificates.crt', Chris@0: // FreeBSD (provided by the ca_root_nss package) Chris@0: '/usr/local/share/certs/ca-root-nss.crt', Chris@0: // SLES 12 (provided by the ca-certificates package) Chris@0: '/var/lib/ca-certificates/ca-bundle.pem', Chris@0: // OS X provided by homebrew (using the default path) Chris@0: '/usr/local/etc/openssl/cert.pem', Chris@0: // Google app engine Chris@0: '/etc/ca-certificates.crt', Chris@0: // Windows? Chris@0: 'C:\\windows\\system32\\curl-ca-bundle.crt', Chris@0: 'C:\\windows\\curl-ca-bundle.crt', Chris@0: ]; Chris@0: Chris@0: if ($cached) { Chris@0: return $cached; Chris@0: } Chris@0: Chris@0: if ($ca = ini_get('openssl.cafile')) { Chris@0: return $cached = $ca; Chris@0: } Chris@0: Chris@0: if ($ca = ini_get('curl.cainfo')) { Chris@0: return $cached = $ca; Chris@0: } Chris@0: Chris@0: foreach ($cafiles as $filename) { Chris@0: if (file_exists($filename)) { Chris@0: return $cached = $filename; Chris@0: } Chris@0: } Chris@0: Chris@0: throw new \RuntimeException(<<< EOT Chris@0: No system CA bundle could be found in any of the the common system locations. Chris@0: PHP versions earlier than 5.6 are not properly configured to use the system's Chris@0: CA bundle by default. In order to verify peer certificates, you will need to Chris@0: supply the path on disk to a certificate bundle to the 'verify' request Chris@0: option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not Chris@0: need a specific certificate bundle, then Mozilla provides a commonly used CA Chris@0: bundle which can be downloaded here (provided by the maintainer of cURL): Chris@0: https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once Chris@0: you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP Chris@0: ini setting to point to the path to the file, allowing you to omit the 'verify' Chris@0: request option. See http://curl.haxx.se/docs/sslcerts.html for more Chris@0: information. Chris@0: EOT Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Creates an associative array of lowercase header names to the actual Chris@0: * header casing. Chris@0: * Chris@0: * @param array $headers Chris@0: * Chris@0: * @return array Chris@0: */ Chris@0: function normalize_header_keys(array $headers) Chris@0: { Chris@0: $result = []; Chris@0: foreach (array_keys($headers) as $key) { Chris@0: $result[strtolower($key)] = $key; Chris@0: } Chris@0: Chris@0: return $result; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns true if the provided host matches any of the no proxy areas. Chris@0: * Chris@0: * This method will strip a port from the host if it is present. Each pattern Chris@0: * can be matched with an exact match (e.g., "foo.com" == "foo.com") or a Chris@0: * partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" == Chris@0: * "baz.foo.com", but ".foo.com" != "foo.com"). Chris@0: * Chris@0: * Areas are matched in the following cases: Chris@0: * 1. "*" (without quotes) always matches any hosts. Chris@0: * 2. An exact match. Chris@0: * 3. The area starts with "." and the area is the last part of the host. e.g. Chris@0: * '.mit.edu' will match any host that ends with '.mit.edu'. Chris@0: * Chris@0: * @param string $host Host to check against the patterns. Chris@0: * @param array $noProxyArray An array of host patterns. Chris@0: * Chris@0: * @return bool Chris@0: */ Chris@0: function is_host_in_noproxy($host, array $noProxyArray) Chris@0: { Chris@0: if (strlen($host) === 0) { Chris@0: throw new \InvalidArgumentException('Empty host provided'); Chris@0: } Chris@0: Chris@0: // Strip port if present. Chris@0: if (strpos($host, ':')) { Chris@0: $host = explode($host, ':', 2)[0]; Chris@0: } Chris@0: Chris@0: foreach ($noProxyArray as $area) { Chris@0: // Always match on wildcards. Chris@0: if ($area === '*') { Chris@0: return true; Chris@0: } elseif (empty($area)) { Chris@0: // Don't match on empty values. Chris@0: continue; Chris@0: } elseif ($area === $host) { Chris@0: // Exact matches. Chris@0: return true; Chris@0: } else { Chris@0: // Special match if the area when prefixed with ".". Remove any Chris@0: // existing leading "." and add a new leading ".". Chris@0: $area = '.' . ltrim($area, '.'); Chris@0: if (substr($host, -(strlen($area))) === $area) { Chris@0: return true; Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: return false; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Wrapper for json_decode that throws when an error occurs. Chris@0: * Chris@0: * @param string $json JSON data to parse Chris@0: * @param bool $assoc When true, returned objects will be converted Chris@0: * into associative arrays. Chris@0: * @param int $depth User specified recursion depth. Chris@0: * @param int $options Bitmask of JSON decode options. Chris@0: * Chris@0: * @return mixed Chris@0: * @throws \InvalidArgumentException if the JSON cannot be decoded. Chris@0: * @link http://www.php.net/manual/en/function.json-decode.php Chris@0: */ Chris@0: function json_decode($json, $assoc = false, $depth = 512, $options = 0) Chris@0: { Chris@0: $data = \json_decode($json, $assoc, $depth, $options); Chris@0: if (JSON_ERROR_NONE !== json_last_error()) { Chris@0: throw new \InvalidArgumentException( Chris@13: 'json_decode error: ' . json_last_error_msg() Chris@13: ); Chris@0: } Chris@0: Chris@0: return $data; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Wrapper for JSON encoding that throws when an error occurs. Chris@0: * Chris@0: * @param mixed $value The value being encoded Chris@0: * @param int $options JSON encode option bitmask Chris@0: * @param int $depth Set the maximum depth. Must be greater than zero. Chris@0: * Chris@0: * @return string Chris@0: * @throws \InvalidArgumentException if the JSON cannot be encoded. Chris@0: * @link http://www.php.net/manual/en/function.json-encode.php Chris@0: */ Chris@0: function json_encode($value, $options = 0, $depth = 512) Chris@0: { Chris@0: $json = \json_encode($value, $options, $depth); Chris@0: if (JSON_ERROR_NONE !== json_last_error()) { Chris@0: throw new \InvalidArgumentException( Chris@13: 'json_encode error: ' . json_last_error_msg() Chris@13: ); Chris@0: } Chris@0: Chris@0: return $json; Chris@0: }