get = new ReadonlyParameterCollection(!empty($get) ? $get : (array)$_GET); $this->post = new ReadonlyParameterCollection(!empty($post) ? $post : (array)$_POST); $this->files = new FilesCollection(!empty($files) ? $files : (array)$_FILES); $this->server = new ServerParameter(!empty($server) ? $server : (array)$_SERVER); $this->cookie = new ReadonlyParameterCollection(!empty($cookie) ? $cookie : (array)$_COOKIE); $this->header = new ReadonlyParameterCollection($this->server->getHeaders()); $this->attributes = new ParameterCollection([]); $this->method = $this->getMethod(); $this->requestUri = $this->getRequestUri(); $this->pathInfo = $this->getPathInfo(); $this->content = $content; } /** * Returns an instance of Request created with php's superglobals. * * @param string|null $content * * @return Request */ public static function createFromGlobals($content = null) { $request = new static((array)$_GET, (array)$_POST, (array)$_FILES, (array)$_SERVER, (array)$_COOKIE, $content); if ( $request->server->get('CONTENT_TYPE') === 'application/x-www-form-urlencoded' && strtoupper($request->server->get('REQUEST_METHOD')) === 'PUT' ) { parse_str($request->getContent(), $postParams); $request->post = new ReadonlyParameterCollection($postParams); } return $request; } /** * Gets a $_GET parameter value * * @param string $name * @param mixed|null $default * * @return mixed */ public function getGet($name, $default = null) { return $this->get->get($name, $default); } /** * Gets a $_POST parameter value * * @param string $name * @param mixed|null $default * * @return mixed */ public function getPost($name, $default = null) { return $this->post->get($name, $default); } /** * Gets a $_GET or $_POST parameter value * * Looks at $_GET parameters first. * * @param string $name * @param mixed|null $default * * @return mixed */ public function getParam($name, $default = null) { if ($this->get->has($name)) { return $this->get->get($name); } if ($this->post->has($name)) { return $this->post->get($name); } return $default; } /** * Gets a $_FILES parameter value * * @param string $name * @param mixed|null $default * * @return FileUpload|mixed */ public function getFile($name, $default = null) { return $this->files->get($name, $default); } /** * Gets a $_SERVER parameter value * * @param string $name * @param mixed|null $default * * @return mixed */ public function getServer($name, $default = null) { return $this->server->get($name, $default); } /** * Gets a HTTP header value * * Use the HTTP header name as used in the Browser. * * @example getHeader('Content-Type') returns 'text' * @example getHeader('CONTENT_TYPE') returns null * * @param string $name * @param mixed|null $default * * @return mixed */ public function getHeader($name, $default = null) { return $this->header->get($name, $default); } /** * Gets a $_COOKIE parameter value * * @param string $name * @param mixed|null $default * * @return mixed */ public function getCookie($name, $default = null) { return $this->cookie->get($name, $default); } /** * Returns true if a secure protocol was used. * * @return bool */ public function isSecure() { if ($this->server->get('HTTPS') === 'on') { return true; } if ($this->server->get('HTTP_X_FORWARDED_SSL') === 'on') { return true; } if ($this->server->get('HTTP_X_FORWARDED_PROTO') === 'https') { return true; } return false; } /** * Returns true if the request is an ajax request. * * @return bool */ public function isAjax() { return strtolower($this->server->get('HTTP_X_REQUESTED_WITH')) === 'xmlhttprequest'; } /** * Returns true if the request was issued via command line. * * @return bool */ public function isCli() { return php_sapi_name() === 'cli'; } /** * Gets the HTTP method. * * @return string */ public function getMethod() { if ($this->method === null) { $method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); if (!in_array($method, self::$supportedMethods, true)) { throw new MethodNotAllowedException(self::$supportedMethods); } $this->method = $method; } return $this->method; } /** * Gets the request URI. * * Same as $_SERVER['REQUEST_URI'] * * @return string */ public function getRequestUri() { if (null === $this->requestUri) { $this->requestUri = $this->server->get('REQUEST_URI'); } return $this->requestUri; } /** * Get path info from the request. * * @return string */ public function getPathInfo() { if (null === $this->pathInfo) { $this->pathInfo = !empty($this->server->get('PATH_INFO')) ? $this->server->get('PATH_INFO') : ''; } return $this->pathInfo; } /** * Returns protocol and hostname. * * @example 'http://www.xentral.com' * * @return string */ public function getSchemeAndHttpHost() { $protocol = 'http'; if ($this->isSecure() || strtolower($this->server->get('REQUEST_SCHEME')) === 'https') { $protocol = 'https'; } return sprintf( '%s://%s', $protocol, $this->server->get('HTTP_HOST') ); } /** * Returns the full URL with GET parameters. * * @example ->'http://www.xentral.com/path/index.php?param=1¶m2=2' * * @return string */ public function getFullUrl() { return $this->getSchemeAndHttpHost() . $this->getRequestUri(); } /** * Returns the URL without GET parameters. * * @example 'http://www.xentral.com/path/index.php?var=1' -> 'http://www.xentral.com/path' * @example 'http://www.xentral.com/path/?var=1' -> 'http://www.xentral.com/path' * @example 'http://www.xentral.com/path?var=1' -> 'http://www.xentral.com' * * @return string */ public function getBaseUrl() { $baseUrl = ''; $uri = $this->getRequestUri(); $uri = preg_replace('/([^?]+)[?]?.*/', '\1', $uri); $uriParts = explode('/', $uri); for ($i=0; $i < count($uriParts)-1; $i++) { if( $uriParts[$i] !== '') { $baseUrl .= '/' . $uriParts[$i]; } } $baseUrl = $this->getSchemeAndHttpHost() . $baseUrl; //Failsafe? // $queryString = $this->server->get('QUERY_STRING'); // parse_str($queryString, $queryParts); // // /** @see /www/api/docs.html#failsafe */ // if (isset($queryParts['path'])) { // return sprintf('%s?path=%s', $baseUrl, $queryParts['path']); // } return $baseUrl; } /** * Appends specified path to the URL. * * @example getUrlForPath('/path') -> 'http://www.xentral.com/path' * * @param string $path must starts with a slash '/' * * @return string */ public function getUrlForPath($path) { if (!preg_match('/^\/.*$/', $path)) { throw new InvalidArgumentException('The first argument must start with a slash "/"'); } $schemeAndHost = $this->getSchemeAndHttpHost(); $urlPath = preg_replace('/^(.*)\/[^\/]*$/', '\1', $this->server->get('SCRIPT_NAME')); return sprintf('%s%s%s', $schemeAndHost, $urlPath, $path); } /** *Returns the path between the URI and the current SCRIPT_NAME * * @example 'http://www.xentral.com/www/api/v1/dateien/50' -> '/v1/dateien/50' * * @return string */ public function getBasePath() { $basePath = ''; $scriptNameParts = explode('/', $this->server->get('SCRIPT_NAME')); $uri = preg_replace('/([^?]+)[?]?.*/', '\1', $this->server->get('REQUEST_URI')); $uriParts = explode('/', $uri); for($i=0; $i < count($uriParts)-0; $i++) { if (!isset($scriptNameParts[$i]) || $scriptNameParts[$i] !== $uriParts[$i]) { $basePath .= '/'. $uriParts[$i]; } } if($basePath === '') { $basePath = '/'; } return $basePath; } /** * @deprecated Use getFullUrl or getBaseUrl instead! * * @param bool $withQueryParams GET-Parameter mitliefern? * * @return string */ public function getFullUri($withQueryParams = true) { $scheme = $this->server->get('REQUEST_SCHEME'); $hostAndPort = $this->server->get('HTTP_HOST'); $requestUri = $this->server->get('REQUEST_URI'); $fullUriWithQueryParams = sprintf('%s://%s%s', $scheme, $hostAndPort, $requestUri); if ($withQueryParams === true) { return $fullUriWithQueryParams; } /* * Nachfolgend werden die GET-Parameter aus der Uri entfernt */ $offset = strpos($fullUriWithQueryParams, '?'); $fullUriWithoutQueryParams = $offset !== false ? substr_replace($fullUriWithQueryParams, '', $offset) : $fullUriWithQueryParams; // Query-String zerlegen $queryString = $this->server->get('QUERY_STRING'); parse_str($queryString, $queryParts); /** @see /www/api/docs.html#failsafe */ if (isset($queryParts['path'])) { return $fullUriWithoutQueryParams . '?path=' . $queryParts['path']; } return $fullUriWithoutQueryParams; } /** * Returns true if the failsafe URL was used for the request * * @example Failsafe-Uri: /api/index.php?path=/v1/adressen * * @see /www/api/docs.html#failsafe * * @return bool */ public function isFailsafeUri() { $queryString = $this->server->get('QUERY_STRING'); parse_str($queryString, $queryParts); return isset($queryParts['path']); } /** * Returns the request body. * * @return string */ public function getContent() { if (null === $this->content) { $this->content = file_get_contents('php://input'); } return !empty($this->content) ? $this->content : ''; } /** * Return a JSON request body as php object * * @return object */ public function getJson() : object { return json_decode($this->getContent()); } /** * Returns the content type of the request. * * @return string|null [json|xml|html|...] null if not set */ public function getContentType() { $contentTypeRaw = $this->header->get('Content-Type'); if ($contentTypeRaw === null || $contentTypeRaw === '') { return null; } // Boundary bei Multipart Content-Type entfernen // @example "Content-Type: multipart/form-data; boundary=gc0p4Jq0M2Yt08jU534c0p" $posSemicolon = strpos($contentTypeRaw, ';'); if ($posSemicolon !== false) { $contentTypeRaw = trim(substr($contentTypeRaw, 0, $posSemicolon)); } $typeParts = explode('/', strtolower($contentTypeRaw)); if (count($typeParts) < 2) { throw new HttpException(400, sprintf('Invalid content type "%s".', $contentTypeRaw)); } return $typeParts[1]; } /** * Gets the data types from the HTTP Accept header. * * @return array [] if not set */ public function getAcceptableContentTypes() { if (null === $this->acceptableContentTypes) { $acceptHeaderRaw = $this->header->get('Accept'); $acceptParts = explode(',', $acceptHeaderRaw); $acceptable = []; foreach ($acceptParts as $acceptPart) { if ($pos = strpos($acceptPart, ';')) { // Priorität abschneiden $acceptPart = substr($acceptPart, 0, $pos); } $acceptable[] = trim($acceptPart); } $this->acceptableContentTypes = $acceptable; } return $this->acceptableContentTypes; } }