1<?php
2
3/**
4 * @see       https://github.com/laminas/laminas-diactoros for the canonical source repository
5 * @copyright https://github.com/laminas/laminas-diactoros/blob/master/COPYRIGHT.md
6 * @license   https://github.com/laminas/laminas-diactoros/blob/master/LICENSE.md New BSD License
7 */
8
9namespace Laminas\Diactoros;
10
11use InvalidArgumentException;
12use Psr\Http\Message\UploadedFileInterface;
13use stdClass;
14use UnexpectedValueException;
15
16use function array_change_key_case;
17use function array_key_exists;
18use function explode;
19use function implode;
20use function is_array;
21use function is_callable;
22use function strtolower;
23
24use const CASE_LOWER;
25
26/**
27 * Class for marshaling a request object from the current PHP environment.
28 *
29 * Logic largely refactored from the Laminas Laminas\Http\PhpEnvironment\Request class.
30 *
31 * @copyright Copyright (c) 2005-2015 Laminas (https://www.zend.com)
32 * @license   https://getlaminas.org/license/new-bsd New BSD License
33 */
34abstract class ServerRequestFactory
35{
36    /**
37     * Function to use to get apache request headers; present only to simplify mocking.
38     *
39     * @var callable
40     */
41    private static $apacheRequestHeaders = 'apache_request_headers';
42
43    /**
44     * Create a request from the supplied superglobal values.
45     *
46     * If any argument is not supplied, the corresponding superglobal value will
47     * be used.
48     *
49     * The ServerRequest created is then passed to the fromServer() method in
50     * order to marshal the request URI and headers.
51     *
52     * @see fromServer()
53     * @param array $server $_SERVER superglobal
54     * @param array $query $_GET superglobal
55     * @param array $body $_POST superglobal
56     * @param array $cookies $_COOKIE superglobal
57     * @param array $files $_FILES superglobal
58     * @return ServerRequest
59     * @throws InvalidArgumentException for invalid file values
60     */
61    public static function fromGlobals(
62        array $server = null,
63        array $query = null,
64        array $body = null,
65        array $cookies = null,
66        array $files = null
67    ) {
68        $server = normalizeServer(
69            $server ?: $_SERVER,
70            is_callable(self::$apacheRequestHeaders) ? self::$apacheRequestHeaders : null
71        );
72        $files   = normalizeUploadedFiles($files ?: $_FILES);
73        $headers = marshalHeadersFromSapi($server);
74
75        if (null === $cookies && array_key_exists('cookie', $headers)) {
76            $cookies = parseCookieHeader($headers['cookie']);
77        }
78
79        return new ServerRequest(
80            $server,
81            $files,
82            marshalUriFromSapi($server, $headers),
83            marshalMethodFromSapi($server),
84            'php://input',
85            $headers,
86            $cookies ?: $_COOKIE,
87            $query ?: $_GET,
88            $body ?: $_POST,
89            marshalProtocolVersionFromSapi($server)
90        );
91    }
92
93    /**
94     * Access a value in an array, returning a default value if not found
95     *
96     * @deprecated since 1.8.0; no longer used internally.
97     * @param string $key
98     * @param array $values
99     * @param mixed $default
100     * @return mixed
101     */
102    public static function get($key, array $values, $default = null)
103    {
104        if (array_key_exists($key, $values)) {
105            return $values[$key];
106        }
107
108        return $default;
109    }
110
111    /**
112     * Search for a header value.
113     *
114     * Does a case-insensitive search for a matching header.
115     *
116     * If found, it is returned as a string, using comma concatenation.
117     *
118     * If not, the $default is returned.
119     *
120     * @deprecated since 1.8.0; no longer used internally.
121     * @param string $header
122     * @param array $headers
123     * @param mixed $default
124     * @return string
125     */
126    public static function getHeader($header, array $headers, $default = null)
127    {
128        $header  = strtolower($header);
129        $headers = array_change_key_case($headers, CASE_LOWER);
130        if (array_key_exists($header, $headers)) {
131            $value = is_array($headers[$header]) ? implode(', ', $headers[$header]) : $headers[$header];
132            return $value;
133        }
134
135        return $default;
136    }
137
138    /**
139     * Marshal the $_SERVER array
140     *
141     * Pre-processes and returns the $_SERVER superglobal.
142     *
143     * @deprected since 1.8.0; use Laminas\Diactoros\normalizeServer() instead.
144     * @param array $server
145     * @return array
146     */
147    public static function normalizeServer(array $server)
148    {
149        return normalizeServer(
150            $server ?: $_SERVER,
151            is_callable(self::$apacheRequestHeaders) ? self::$apacheRequestHeaders : null
152        );
153    }
154
155    /**
156     * Normalize uploaded files
157     *
158     * Transforms each value into an UploadedFileInterface instance, and ensures
159     * that nested arrays are normalized.
160     *
161     * @deprecated since 1.8.0; use \Laminas\Diactoros\normalizeUploadedFiles instead.
162     * @param array $files
163     * @return array
164     * @throws InvalidArgumentException for unrecognized values
165     */
166    public static function normalizeFiles(array $files)
167    {
168        return normalizeUploadedFiles($files);
169    }
170
171    /**
172     * Marshal headers from $_SERVER
173     *
174     * @deprecated since 1.8.0; use Laminas\Diactoros\marshalHeadersFromSapi().
175     * @param array $server
176     * @return array
177     */
178    public static function marshalHeaders(array $server)
179    {
180        return marshalHeadersFromSapi($server);
181    }
182
183    /**
184     * Marshal the URI from the $_SERVER array and headers
185     *
186     * @deprecated since 1.8.0; use Laminas\Diactoros\marshalUriFromSapi() instead.
187     * @param array $server
188     * @param array $headers
189     * @return Uri
190     */
191    public static function marshalUriFromServer(array $server, array $headers)
192    {
193        return marshalUriFromSapi($server, $headers);
194    }
195
196    /**
197     * Marshal the host and port from HTTP headers and/or the PHP environment
198     *
199     * @deprecated since 1.8.0; use Laminas\Diactoros\marshalUriFromSapi() instead,
200     *     and pull the host and port from the Uri instance that function
201     *     returns.
202     * @param stdClass $accumulator
203     * @param array $server
204     * @param array $headers
205     */
206    public static function marshalHostAndPortFromHeaders(stdClass $accumulator, array $server, array $headers)
207    {
208        $uri = marshalUriFromSapi($server, $headers);
209        $accumulator->host = $uri->getHost();
210        $accumulator->port = $uri->getPort();
211    }
212
213    /**
214     * Detect the base URI for the request
215     *
216     * Looks at a variety of criteria in order to attempt to autodetect a base
217     * URI, including rewrite URIs, proxy URIs, etc.
218     *
219     * @deprecated since 1.8.0; use Laminas\Diactoros\marshalUriFromSapi() instead,
220     *     and pull the path from the Uri instance that function returns.
221     * @param array $server
222     * @return string
223     */
224    public static function marshalRequestUri(array $server)
225    {
226        $uri = marshalUriFromSapi($server, []);
227        return $uri->getPath();
228    }
229
230    /**
231     * Strip the query string from a path
232     *
233     * @deprecated since 1.8.0; no longer used internally.
234     * @param mixed $path
235     * @return string
236     */
237    public static function stripQueryString($path)
238    {
239        return explode('?', $path, 2)[0];
240    }
241}
242