vendor/ezimuel/ringphp/src/Core.php line 334

Open in your IDE?
  1. <?php
  2. namespace GuzzleHttp\Ring;
  3. use GuzzleHttp\Stream\StreamInterface;
  4. use GuzzleHttp\Ring\Future\FutureArrayInterface;
  5. use GuzzleHttp\Ring\Future\FutureArray;
  6. /**
  7.  * Provides core functionality of Ring handlers and middleware.
  8.  */
  9. class Core
  10. {
  11.     /**
  12.      * Returns a function that calls all of the provided functions, in order,
  13.      * passing the arguments provided to the composed function to each function.
  14.      *
  15.      * @param callable[] $functions Array of functions to proxy to.
  16.      *
  17.      * @return callable
  18.      */
  19.     public static function callArray(array $functions)
  20.     {
  21.         return function () use ($functions) {
  22.             $args func_get_args();
  23.             foreach ($functions as $fn) {
  24.                 call_user_func_array($fn$args);
  25.             }
  26.         };
  27.     }
  28.     /**
  29.      * Gets an array of header line values from a message for a specific header
  30.      *
  31.      * This method searches through the "headers" key of a message for a header
  32.      * using a case-insensitive search.
  33.      *
  34.      * @param array  $message Request or response hash.
  35.      * @param string $header  Header to retrieve
  36.      *
  37.      * @return array
  38.      */
  39.     public static function headerLines($message$header)
  40.     {
  41.         $result = [];
  42.         if (!empty($message['headers'])) {
  43.             foreach ($message['headers'] as $name => $value) {
  44.                 if (!strcasecmp($name$header)) {
  45.                     $result array_merge($result$value);
  46.                 }
  47.             }
  48.         }
  49.         return $result;
  50.     }
  51.     /**
  52.      * Gets a header value from a message as a string or null
  53.      *
  54.      * This method searches through the "headers" key of a message for a header
  55.      * using a case-insensitive search. The lines of the header are imploded
  56.      * using commas into a single string return value.
  57.      *
  58.      * @param array  $message Request or response hash.
  59.      * @param string $header  Header to retrieve
  60.      *
  61.      * @return string|null Returns the header string if found, or null if not.
  62.      */
  63.     public static function header($message$header)
  64.     {
  65.         $match self::headerLines($message$header);
  66.         return $match implode(', '$match) : null;
  67.     }
  68.     /**
  69.      * Returns the first header value from a message as a string or null. If
  70.      * a header line contains multiple values separated by a comma, then this
  71.      * function will return the first value in the list.
  72.      *
  73.      * @param array  $message Request or response hash.
  74.      * @param string $header  Header to retrieve
  75.      *
  76.      * @return string|null Returns the value as a string if found.
  77.      */
  78.     public static function firstHeader($message$header)
  79.     {
  80.         if (!empty($message['headers'])) {
  81.             foreach ($message['headers'] as $name => $value) {
  82.                 if (!strcasecmp($name$header)) {
  83.                     // Return the match itself if it is a single value.
  84.                     $pos strpos($value[0], ',');
  85.                     return $pos substr($value[0], 0$pos) : $value[0];
  86.                 }
  87.             }
  88.         }
  89.         return null;
  90.     }
  91.     /**
  92.      * Returns true if a message has the provided case-insensitive header.
  93.      *
  94.      * @param array  $message Request or response hash.
  95.      * @param string $header  Header to check
  96.      *
  97.      * @return bool
  98.      */
  99.     public static function hasHeader($message$header)
  100.     {
  101.         if (!empty($message['headers'])) {
  102.             foreach ($message['headers'] as $name => $value) {
  103.                 if (!strcasecmp($name$header)) {
  104.                     return true;
  105.                 }
  106.             }
  107.         }
  108.         return false;
  109.     }
  110.     /**
  111.      * Parses an array of header lines into an associative array of headers.
  112.      *
  113.      * @param array $lines Header lines array of strings in the following
  114.      *                     format: "Name: Value"
  115.      * @return array
  116.      */
  117.     public static function headersFromLines($lines)
  118.     {
  119.         $headers = [];
  120.         foreach ($lines as $line) {
  121.             $parts explode(':'$line2);
  122.             $headers[trim($parts[0])][] = isset($parts[1])
  123.                 ? trim($parts[1])
  124.                 : null;
  125.         }
  126.         return $headers;
  127.     }
  128.     /**
  129.      * Removes a header from a message using a case-insensitive comparison.
  130.      *
  131.      * @param array  $message Message that contains 'headers'
  132.      * @param string $header  Header to remove
  133.      *
  134.      * @return array
  135.      */
  136.     public static function removeHeader(array $message$header)
  137.     {
  138.         if (isset($message['headers'])) {
  139.             foreach (array_keys($message['headers']) as $key) {
  140.                 if (!strcasecmp($header$key)) {
  141.                     unset($message['headers'][$key]);
  142.                 }
  143.             }
  144.         }
  145.         return $message;
  146.     }
  147.     /**
  148.      * Replaces any existing case insensitive headers with the given value.
  149.      *
  150.      * @param array  $message Message that contains 'headers'
  151.      * @param string $header  Header to set.
  152.      * @param array  $value   Value to set.
  153.      *
  154.      * @return array
  155.      */
  156.     public static function setHeader(array $message$header, array $value)
  157.     {
  158.         $message self::removeHeader($message$header);
  159.         $message['headers'][$header] = $value;
  160.         return $message;
  161.     }
  162.     /**
  163.      * Creates a URL string from a request.
  164.      *
  165.      * If the "url" key is present on the request, it is returned, otherwise
  166.      * the url is built up based on the scheme, host, uri, and query_string
  167.      * request values.
  168.      *
  169.      * @param array $request Request to get the URL from
  170.      *
  171.      * @return string Returns the request URL as a string.
  172.      * @throws \InvalidArgumentException if no Host header is present.
  173.      */
  174.     public static function url(array $request)
  175.     {
  176.         if (isset($request['url'])) {
  177.             return $request['url'];
  178.         }
  179.         $uri = (isset($request['scheme'])
  180.                 ? $request['scheme'] : 'http') . '://';
  181.         if ($host self::header($request'host')) {
  182.             $uri .= $host;
  183.         } else {
  184.             throw new \InvalidArgumentException('No Host header was provided');
  185.         }
  186.         if (isset($request['uri'])) {
  187.             $uri .= $request['uri'];
  188.         }
  189.         if (isset($request['query_string'])) {
  190.             $uri .= '?' $request['query_string'];
  191.         }
  192.         return $uri;
  193.     }
  194.     /**
  195.      * Reads the body of a message into a string.
  196.      *
  197.      * @param array|FutureArrayInterface $message Array containing a "body" key
  198.      *
  199.      * @return null|string Returns the body as a string or null if not set.
  200.      * @throws \InvalidArgumentException if a request body is invalid.
  201.      */
  202.     public static function body($message)
  203.     {
  204.         if (!isset($message['body'])) {
  205.             return null;
  206.         }
  207.         if ($message['body'] instanceof StreamInterface) {
  208.             return (string) $message['body'];
  209.         }
  210.         switch (gettype($message['body'])) {
  211.             case 'string':
  212.                 return $message['body'];
  213.             case 'resource':
  214.                 return stream_get_contents($message['body']);
  215.             case 'object':
  216.                 if ($message['body'] instanceof \Iterator) {
  217.                     return implode(''iterator_to_array($message['body']));
  218.                 } elseif (method_exists($message['body'], '__toString')) {
  219.                     return (string) $message['body'];
  220.                 }
  221.             default:
  222.                 throw new \InvalidArgumentException('Invalid request body: '
  223.                     self::describeType($message['body']));
  224.         }
  225.     }
  226.     /**
  227.      * Rewind the body of the provided message if possible.
  228.      *
  229.      * @param array $message Message that contains a 'body' field.
  230.      *
  231.      * @return bool Returns true on success, false on failure
  232.      */
  233.     public static function rewindBody($message)
  234.     {
  235.         if ($message['body'] instanceof StreamInterface) {
  236.             return $message['body']->seek(0);
  237.         }
  238.         if ($message['body'] instanceof \Generator) {
  239.             return false;
  240.         }
  241.         if ($message['body'] instanceof \Iterator) {
  242.             $message['body']->rewind();
  243.             return true;
  244.         }
  245.         if (is_resource($message['body'])) {
  246.             return rewind($message['body']);
  247.         }
  248.         return is_string($message['body'])
  249.             || (is_object($message['body'])
  250.                 && method_exists($message['body'], '__toString'));
  251.     }
  252.     /**
  253.      * Debug function used to describe the provided value type and class.
  254.      *
  255.      * @param mixed $input
  256.      *
  257.      * @return string Returns a string containing the type of the variable and
  258.      *                if a class is provided, the class name.
  259.      */
  260.     public static function describeType($input)
  261.     {
  262.         switch (gettype($input)) {
  263.             case 'object':
  264.                 return 'object(' get_class($input) . ')';
  265.             case 'array':
  266.                 return 'array(' count($input) . ')';
  267.             default:
  268.                 ob_start();
  269.                 var_dump($input);
  270.                 // normalize float vs double
  271.                 return str_replace('double(''float('rtrim(ob_get_clean()));
  272.         }
  273.     }
  274.     /**
  275.      * Sleep for the specified amount of time specified in the request's
  276.      * ['client']['delay'] option if present.
  277.      *
  278.      * This function should only be used when a non-blocking sleep is not
  279.      * possible.
  280.      *
  281.      * @param array $request Request to sleep
  282.      */
  283.     public static function doSleep(array $request)
  284.     {
  285.         if (isset($request['client']['delay'])) {
  286.             usleep($request['client']['delay'] * 1000);
  287.         }
  288.     }
  289.     /**
  290.      * Returns a proxied future that modifies the dereferenced value of another
  291.      * future using a promise.
  292.      *
  293.      * @param FutureArrayInterface $future      Future to wrap with a new future
  294.      * @param callable    $onFulfilled Invoked when the future fulfilled
  295.      * @param callable    $onRejected  Invoked when the future rejected
  296.      * @param callable    $onProgress  Invoked when the future progresses
  297.      *
  298.      * @return FutureArray
  299.      */
  300.     public static function proxy(
  301.         FutureArrayInterface $future,
  302.         callable $onFulfilled null,
  303.         callable $onRejected null,
  304.         callable $onProgress null
  305.     ) {
  306.         return new FutureArray(
  307.             $future->then($onFulfilled$onRejected$onProgress),
  308.             [$future'wait'],
  309.             [$future'cancel']
  310.         );
  311.     }
  312.     /**
  313.      * Returns a debug stream based on the provided variable.
  314.      *
  315.      * @param mixed $value Optional value
  316.      *
  317.      * @return resource
  318.      */
  319.     public static function getDebugResource($value null)
  320.     {
  321.         if (is_resource($value)) {
  322.             return $value;
  323.         } elseif (defined('STDOUT')) {
  324.             return STDOUT;
  325.         } else {
  326.             return fopen('php://output''w');
  327.         }
  328.     }
  329. }