'php', 'cookiePath' => $uri->webroot ]; $session = Session::create($sessionConfig); $request = new ServerRequest([ 'environment' => $server, 'uri' => $uri, 'files' => $files ?: $_FILES, 'cookies' => $cookies ?: $_COOKIE, 'query' => $query ?: $_GET, 'post' => $body ?: $_POST, 'webroot' => $uri->webroot, 'base' => $uri->base, 'session' => $session, ]); return $request; } /** * Create a new Uri instance from the provided server data. * * @param array $server Array of server data to build the Uri from. * $_SERVER will be added into the $server parameter. * @return \Psr\Http\Message\UriInterface New instance. */ public static function createUri(array $server = []) { $server += $_SERVER; $server = static::normalizeServer($server); $headers = static::marshalHeaders($server); return static::marshalUriFromServer($server, $headers); } /** * Build a UriInterface object. * * Add in some CakePHP specific logic/properties that help * perserve backwards compatibility. * * @param array $server The server parameters. * @param array $headers The normalized headers * @return \Psr\Http\Message\UriInterface a constructed Uri */ public static function marshalUriFromServer(array $server, array $headers) { $uri = parent::marshalUriFromServer($server, $headers); list($base, $webroot) = static::getBase($uri, $server); // Look in PATH_INFO first, as this is the exact value we need prepared // by PHP. $pathInfo = Hash::get($server, 'PATH_INFO'); if ($pathInfo) { $uri = $uri->withPath($pathInfo); } else { $uri = static::updatePath($base, $uri); } // Splat on some extra attributes to save // some method calls. $uri->base = $base; $uri->webroot = $webroot; return $uri; } /** * Updates the request URI to remove the base directory. * * @param string $base The base path to remove. * @param \Psr\Http\Message\UriInterface $uri The uri to update. * @return \Psr\Http\Message\UriInterface The modified Uri instance. */ protected static function updatePath($base, $uri) { $path = $uri->getPath(); if (strlen($base) > 0 && strpos($path, $base) === 0) { $path = substr($path, strlen($base)); } if ($path === '/index.php' && $uri->getQuery()) { $path = $uri->getQuery(); } if (empty($path) || $path === '/' || $path === '//' || $path === '/index.php') { $path = '/'; } $endsWithIndex = '/webroot/index.php'; $endsWithLength = strlen($endsWithIndex); if (strlen($path) >= $endsWithLength && substr($path, -$endsWithLength) === $endsWithIndex ) { $path = '/'; } return $uri->withPath($path); } /** * Calculate the base directory and webroot directory. * * @param \Psr\Http\Message\UriInterface $uri The Uri instance. * @param array $server The SERVER data to use. * @return array An array containing the [baseDir, webroot] */ protected static function getBase($uri, $server) { $base = $webroot = $baseUrl = null; $config = Configure::read('App'); extract($config); if ($base !== false && $base !== null) { return [$base, $base . '/']; } if (!$baseUrl) { $base = dirname(Hash::get($server, 'PHP_SELF')); // Clean up additional / which cause following code to fail.. $base = preg_replace('#/+#', '/', $base); $indexPos = strpos($base, '/' . $webroot . '/index.php'); if ($indexPos !== false) { $base = substr($base, 0, $indexPos) . '/' . $webroot; } if ($webroot === basename($base)) { $base = dirname($base); } if ($base === DIRECTORY_SEPARATOR || $base === '.') { $base = ''; } $base = implode('/', array_map('rawurlencode', explode('/', $base))); return [$base, $base . '/']; } $file = '/' . basename($baseUrl); $base = dirname($baseUrl); if ($base === DIRECTORY_SEPARATOR || $base === '.') { $base = ''; } $webrootDir = $base . '/'; $docRoot = Hash::get($server, 'DOCUMENT_ROOT'); $docRootContainsWebroot = strpos($docRoot, $webroot); if (!empty($base) || !$docRootContainsWebroot) { if (strpos($webrootDir, '/' . $webroot . '/') === false) { $webrootDir .= $webroot . '/'; } } return [$base . $file, $webrootDir]; } }