diff --git a/src/Illuminate/Http/Concerns/InteractsWithContentTypes.php b/src/Illuminate/Http/Concerns/InteractsWithContentTypes.php new file mode 100644 index 000000000000..492c131b26f0 --- /dev/null +++ b/src/Illuminate/Http/Concerns/InteractsWithContentTypes.php @@ -0,0 +1,157 @@ +header('CONTENT_TYPE'), ['/json', '+json']); + } + + /** + * Determine if the current request probably expects a JSON response. + * + * @return bool + */ + public function expectsJson() + { + return ($this->ajax() && ! $this->pjax()) || $this->wantsJson(); + } + + /** + * Determine if the current request is asking for JSON in return. + * + * @return bool + */ + public function wantsJson() + { + $acceptable = $this->getAcceptableContentTypes(); + + return isset($acceptable[0]) && Str::contains($acceptable[0], ['/json', '+json']); + } + + /** + * Determines whether the current requests accepts a given content type. + * + * @param string|array $contentTypes + * @return bool + */ + public function accepts($contentTypes) + { + $accepts = $this->getAcceptableContentTypes(); + + if (count($accepts) === 0) { + return true; + } + + $types = (array) $contentTypes; + + foreach ($accepts as $accept) { + if ($accept === '*/*' || $accept === '*') { + return true; + } + + foreach ($types as $type) { + if ($this->matchesType($accept, $type) || $accept === strtok($type, '/').'/*') { + return true; + } + } + } + + return false; + } + + /** + * Return the most suitable content type from the given array based on content negotiation. + * + * @param string|array $contentTypes + * @return string|null + */ + public function prefers($contentTypes) + { + $accepts = $this->getAcceptableContentTypes(); + + $contentTypes = (array) $contentTypes; + + foreach ($accepts as $accept) { + if (in_array($accept, ['*/*', '*'])) { + return $contentTypes[0]; + } + + foreach ($contentTypes as $contentType) { + $type = $contentType; + + if (! is_null($mimeType = $this->getMimeType($contentType))) { + $type = $mimeType; + } + + if ($this->matchesType($type, $accept) || $accept === strtok($type, '/').'/*') { + return $contentType; + } + } + } + } + + /** + * Determines whether a request accepts JSON. + * + * @return bool + */ + public function acceptsJson() + { + return $this->accepts('application/json'); + } + + /** + * Determines whether a request accepts HTML. + * + * @return bool + */ + public function acceptsHtml() + { + return $this->accepts('text/html'); + } + + /** + * Get the data format expected in the response. + * + * @param string $default + * @return string + */ + public function format($default = 'html') + { + foreach ($this->getAcceptableContentTypes() as $type) { + if ($format = $this->getFormat($type)) { + return $format; + } + } + + return $default; + } +} diff --git a/src/Illuminate/Http/Concerns/InteractsWithFlashData.php b/src/Illuminate/Http/Concerns/InteractsWithFlashData.php new file mode 100644 index 000000000000..c6b84f2e2212 --- /dev/null +++ b/src/Illuminate/Http/Concerns/InteractsWithFlashData.php @@ -0,0 +1,64 @@ +session()->getOldInput($key, $default); + } + + /** + * Flash the input for the current request to the session. + * + * @return void + */ + public function flash() + { + $this->session()->flashInput($this->input()); + } + + /** + * Flash only some of the input to the session. + * + * @param array|mixed $keys + * @return void + */ + public function flashOnly($keys) + { + $this->session()->flashInput( + $this->only(is_array($keys) ? $keys : func_get_args()) + ); + } + + /** + * Flash only some of the input to the session. + * + * @param array|mixed $keys + * @return void + */ + public function flashExcept($keys) + { + $this->session()->flashInput( + $this->except(is_array($keys) ? $keys : func_get_args()) + ); + } + + /** + * Flush all of the old input from the session. + * + * @return void + */ + public function flush() + { + $this->session()->flashInput([]); + } +} diff --git a/src/Illuminate/Http/Concerns/InteractsWithInput.php b/src/Illuminate/Http/Concerns/InteractsWithInput.php new file mode 100644 index 000000000000..6dfe6ceb35e4 --- /dev/null +++ b/src/Illuminate/Http/Concerns/InteractsWithInput.php @@ -0,0 +1,316 @@ +retrieveItem('server', $key, $default); + } + + /** + * Determine if a header is set on the request. + * + * @param string $key + * @return bool + */ + public function hasHeader($key) + { + return ! is_null($this->header($key)); + } + + /** + * Retrieve a header from the request. + * + * @param string $key + * @param string|array|null $default + * @return string|array + */ + public function header($key = null, $default = null) + { + return $this->retrieveItem('headers', $key, $default); + } + + /** + * Get the bearer token from the request headers. + * + * @return string|null + */ + public function bearerToken() + { + $header = $this->header('Authorization', ''); + + if (Str::startsWith($header, 'Bearer ')) { + return Str::substr($header, 7); + } + } + + /** + * Determine if the request contains a given input item key. + * + * @param string|array $key + * @return bool + */ + public function exists($key) + { + $keys = is_array($key) ? $key : func_get_args(); + + $input = $this->all(); + + foreach ($keys as $value) { + if (! Arr::has($input, $value)) { + return false; + } + } + + return true; + } + + /** + * Determine if the request contains a non-empty value for an input item. + * + * @param string|array $key + * @return bool + */ + public function has($key) + { + $keys = is_array($key) ? $key : func_get_args(); + + foreach ($keys as $value) { + if ($this->isEmptyString($value)) { + return false; + } + } + + return true; + } + + /** + * Determine if the given input key is an empty string for "has". + * + * @param string $key + * @return bool + */ + protected function isEmptyString($key) + { + $value = $this->input($key); + + return ! is_bool($value) && ! is_array($value) && trim((string) $value) === ''; + } + + /** + * Get all of the input and files for the request. + * + * @return array + */ + public function all() + { + return array_replace_recursive($this->input(), $this->allFiles()); + } + + /** + * Retrieve an input item from the request. + * + * @param string $key + * @param string|array|null $default + * @return string|array + */ + public function input($key = null, $default = null) + { + return data_get( + $this->getInputSource()->all() + $this->query->all(), $key, $default + ); + } + + /** + * Get a subset containing the provided keys with values from the input data. + * + * @param array|mixed $keys + * @return array + */ + public function only($keys) + { + $keys = is_array($keys) ? $keys : func_get_args(); + + $results = []; + + $input = $this->all(); + + foreach ($keys as $key) { + Arr::set($results, $key, data_get($input, $key)); + } + + return $results; + } + + /** + * Get all of the input except for a specified array of items. + * + * @param array|mixed $keys + * @return array + */ + public function except($keys) + { + $keys = is_array($keys) ? $keys : func_get_args(); + + $results = $this->all(); + + Arr::forget($results, $keys); + + return $results; + } + + /** + * Intersect an array of items with the input data. + * + * @param array|mixed $keys + * @return array + */ + public function intersect($keys) + { + return array_filter($this->only(is_array($keys) ? $keys : func_get_args())); + } + + /** + * Retrieve a query string item from the request. + * + * @param string $key + * @param string|array|null $default + * @return string|array + */ + public function query($key = null, $default = null) + { + return $this->retrieveItem('query', $key, $default); + } + + /** + * Determine if a cookie is set on the request. + * + * @param string $key + * @return bool + */ + public function hasCookie($key) + { + return ! is_null($this->cookie($key)); + } + + /** + * Retrieve a cookie from the request. + * + * @param string $key + * @param string|array|null $default + * @return string|array + */ + public function cookie($key = null, $default = null) + { + return $this->retrieveItem('cookies', $key, $default); + } + + /** + * Get an array of all of the files on the request. + * + * @return array + */ + public function allFiles() + { + $files = $this->files->all(); + + return $this->convertedFiles + ? $this->convertedFiles + : $this->convertedFiles = $this->convertUploadedFiles($files); + } + + /** + * Convert the given array of Symfony UploadedFiles to custom Laravel UploadedFiles. + * + * @param array $files + * @return array + */ + protected function convertUploadedFiles(array $files) + { + return array_map(function ($file) { + if (is_null($file) || (is_array($file) && empty(array_filter($file)))) { + return $file; + } + + return is_array($file) + ? $this->convertUploadedFiles($file) + : UploadedFile::createFromBase($file); + }, $files); + } + + /** + * Determine if the uploaded data contains a file. + * + * @param string $key + * @return bool + */ + public function hasFile($key) + { + if (! is_array($files = $this->file($key))) { + $files = [$files]; + } + + foreach ($files as $file) { + if ($this->isValidFile($file)) { + return true; + } + } + + return false; + } + + /** + * Check that the given file is a valid file instance. + * + * @param mixed $file + * @return bool + */ + protected function isValidFile($file) + { + return $file instanceof SplFileInfo && $file->getPath() != ''; + } + + /** + * Retrieve a file from the request. + * + * @param string $key + * @param mixed $default + * @return \Illuminate\Http\UploadedFile|array|null + */ + public function file($key = null, $default = null) + { + return data_get($this->allFiles(), $key, $default); + } + + /** + * Retrieve a parameter item from a given source. + * + * @param string $source + * @param string $key + * @param string|array|null $default + * @return string|array + */ + protected function retrieveItem($source, $key, $default) + { + if (is_null($key)) { + return $this->$source->all(); + } + + return $this->$source->get($key, $default); + } +} diff --git a/src/Illuminate/Http/Request.php b/src/Illuminate/Http/Request.php index 14cb51e60468..de926d36ada1 100644 --- a/src/Illuminate/Http/Request.php +++ b/src/Illuminate/Http/Request.php @@ -15,7 +15,10 @@ class Request extends SymfonyRequest implements Arrayable, ArrayAccess { - use Macroable; + use Concerns\InteractsWithContentTypes, + Concerns\InteractsWithFlashData, + Concerns\InteractsWithInput, + Macroable; /** * The decoded JSON content for the request. @@ -258,354 +261,6 @@ public function ips() return $this->getClientIps(); } - /** - * Determine if the request contains a given input item key. - * - * @param string|array $key - * @return bool - */ - public function exists($key) - { - $keys = is_array($key) ? $key : func_get_args(); - - $input = $this->all(); - - foreach ($keys as $value) { - if (! Arr::has($input, $value)) { - return false; - } - } - - return true; - } - - /** - * Determine if the request contains a non-empty value for an input item. - * - * @param string|array $key - * @return bool - */ - public function has($key) - { - $keys = is_array($key) ? $key : func_get_args(); - - foreach ($keys as $value) { - if ($this->isEmptyString($value)) { - return false; - } - } - - return true; - } - - /** - * Determine if the given input key is an empty string for "has". - * - * @param string $key - * @return bool - */ - protected function isEmptyString($key) - { - $value = $this->input($key); - - return ! is_bool($value) && ! is_array($value) && trim((string) $value) === ''; - } - - /** - * Get all of the input and files for the request. - * - * @return array - */ - public function all() - { - return array_replace_recursive($this->input(), $this->allFiles()); - } - - /** - * Retrieve an input item from the request. - * - * @param string $key - * @param string|array|null $default - * @return string|array - */ - public function input($key = null, $default = null) - { - $input = $this->getInputSource()->all() + $this->query->all(); - - return data_get($input, $key, $default); - } - - /** - * Get a subset containing the provided keys with values from the input data. - * - * @param array|mixed $keys - * @return array - */ - public function only($keys) - { - $keys = is_array($keys) ? $keys : func_get_args(); - - $results = []; - - $input = $this->all(); - - foreach ($keys as $key) { - Arr::set($results, $key, data_get($input, $key)); - } - - return $results; - } - - /** - * Get all of the input except for a specified array of items. - * - * @param array|mixed $keys - * @return array - */ - public function except($keys) - { - $keys = is_array($keys) ? $keys : func_get_args(); - - $results = $this->all(); - - Arr::forget($results, $keys); - - return $results; - } - - /** - * Intersect an array of items with the input data. - * - * @param array|mixed $keys - * @return array - */ - public function intersect($keys) - { - return array_filter($this->only(is_array($keys) ? $keys : func_get_args())); - } - - /** - * Retrieve a query string item from the request. - * - * @param string $key - * @param string|array|null $default - * @return string|array - */ - public function query($key = null, $default = null) - { - return $this->retrieveItem('query', $key, $default); - } - - /** - * Determine if a cookie is set on the request. - * - * @param string $key - * @return bool - */ - public function hasCookie($key) - { - return ! is_null($this->cookie($key)); - } - - /** - * Retrieve a cookie from the request. - * - * @param string $key - * @param string|array|null $default - * @return string|array - */ - public function cookie($key = null, $default = null) - { - return $this->retrieveItem('cookies', $key, $default); - } - - /** - * Get an array of all of the files on the request. - * - * @return array - */ - public function allFiles() - { - $files = $this->files->all(); - - return $this->convertedFiles - ? $this->convertedFiles - : $this->convertedFiles = $this->convertUploadedFiles($files); - } - - /** - * Convert the given array of Symfony UploadedFiles to custom Laravel UploadedFiles. - * - * @param array $files - * @return array - */ - protected function convertUploadedFiles(array $files) - { - return array_map(function ($file) { - if (is_null($file) || (is_array($file) && empty(array_filter($file)))) { - return $file; - } - - return is_array($file) - ? $this->convertUploadedFiles($file) - : UploadedFile::createFromBase($file); - }, $files); - } - - /** - * Determine if the uploaded data contains a file. - * - * @param string $key - * @return bool - */ - public function hasFile($key) - { - if (! is_array($files = $this->file($key))) { - $files = [$files]; - } - - foreach ($files as $file) { - if ($this->isValidFile($file)) { - return true; - } - } - - return false; - } - - /** - * Retrieve a file from the request. - * - * @param string $key - * @param mixed $default - * @return \Illuminate\Http\UploadedFile|array|null - */ - public function file($key = null, $default = null) - { - return data_get($this->allFiles(), $key, $default); - } - - /** - * Check that the given file is a valid file instance. - * - * @param mixed $file - * @return bool - */ - protected function isValidFile($file) - { - return $file instanceof SplFileInfo && $file->getPath() != ''; - } - - /** - * Determine if a header is set on the request. - * - * @param string $key - * @return bool - */ - public function hasHeader($key) - { - return ! is_null($this->header($key)); - } - - /** - * Retrieve a header from the request. - * - * @param string $key - * @param string|array|null $default - * @return string|array - */ - public function header($key = null, $default = null) - { - return $this->retrieveItem('headers', $key, $default); - } - - /** - * Retrieve a server variable from the request. - * - * @param string $key - * @param string|array|null $default - * @return string|array - */ - public function server($key = null, $default = null) - { - return $this->retrieveItem('server', $key, $default); - } - - /** - * Retrieve an old input item. - * - * @param string $key - * @param string|array|null $default - * @return string|array - */ - public function old($key = null, $default = null) - { - return $this->session()->getOldInput($key, $default); - } - - /** - * Flash the input for the current request to the session. - * - * @return void - */ - public function flash() - { - $this->session()->flashInput($this->input()); - } - - /** - * Flash only some of the input to the session. - * - * @param array|mixed $keys - * @return void - */ - public function flashOnly($keys) - { - $this->session()->flashInput( - $this->only(is_array($keys) ? $keys : func_get_args()) - ); - } - - /** - * Flash only some of the input to the session. - * - * @param array|mixed $keys - * @return void - */ - public function flashExcept($keys) - { - $this->session()->flashInput( - $this->except(is_array($keys) ? $keys : func_get_args()) - ); - } - - /** - * Flush all of the old input from the session. - * - * @return void - */ - public function flush() - { - $this->session()->flashInput([]); - } - - /** - * Retrieve a parameter item from a given source. - * - * @param string $source - * @param string $key - * @param string|array|null $default - * @return string|array - */ - protected function retrieveItem($source, $key, $default) - { - if (is_null($key)) { - return $this->$source->all(); - } - - return $this->$source->get($key, $default); - } - /** * Merge new input into the current request's input array. * @@ -662,169 +317,6 @@ protected function getInputSource() return $this->getRealMethod() == 'GET' ? $this->query : $this->request; } - /** - * Determine if the given content types match. - * - * @param string $actual - * @param string $type - * @return bool - */ - public static function matchesType($actual, $type) - { - if ($actual === $type) { - return true; - } - - $split = explode('/', $actual); - - return isset($split[1]) && preg_match('#'.preg_quote($split[0], '#').'/.+\+'.preg_quote($split[1], '#').'#', $type); - } - - /** - * Determine if the request is sending JSON. - * - * @return bool - */ - public function isJson() - { - return Str::contains($this->header('CONTENT_TYPE'), ['/json', '+json']); - } - - /** - * Determine if the current request probably expects a JSON response. - * - * @return bool - */ - public function expectsJson() - { - return ($this->ajax() && ! $this->pjax()) || $this->wantsJson(); - } - - /** - * Determine if the current request is asking for JSON in return. - * - * @return bool - */ - public function wantsJson() - { - $acceptable = $this->getAcceptableContentTypes(); - - return isset($acceptable[0]) && Str::contains($acceptable[0], ['/json', '+json']); - } - - /** - * Determines whether the current requests accepts a given content type. - * - * @param string|array $contentTypes - * @return bool - */ - public function accepts($contentTypes) - { - $accepts = $this->getAcceptableContentTypes(); - - if (count($accepts) === 0) { - return true; - } - - $types = (array) $contentTypes; - - foreach ($accepts as $accept) { - if ($accept === '*/*' || $accept === '*') { - return true; - } - - foreach ($types as $type) { - if ($this->matchesType($accept, $type) || $accept === strtok($type, '/').'/*') { - return true; - } - } - } - - return false; - } - - /** - * Return the most suitable content type from the given array based on content negotiation. - * - * @param string|array $contentTypes - * @return string|null - */ - public function prefers($contentTypes) - { - $accepts = $this->getAcceptableContentTypes(); - - $contentTypes = (array) $contentTypes; - - foreach ($accepts as $accept) { - if (in_array($accept, ['*/*', '*'])) { - return $contentTypes[0]; - } - - foreach ($contentTypes as $contentType) { - $type = $contentType; - - if (! is_null($mimeType = $this->getMimeType($contentType))) { - $type = $mimeType; - } - - if ($this->matchesType($type, $accept) || $accept === strtok($type, '/').'/*') { - return $contentType; - } - } - } - } - - /** - * Determines whether a request accepts JSON. - * - * @return bool - */ - public function acceptsJson() - { - return $this->accepts('application/json'); - } - - /** - * Determines whether a request accepts HTML. - * - * @return bool - */ - public function acceptsHtml() - { - return $this->accepts('text/html'); - } - - /** - * Get the data format expected in the response. - * - * @param string $default - * @return string - */ - public function format($default = 'html') - { - foreach ($this->getAcceptableContentTypes() as $type) { - if ($format = $this->getFormat($type)) { - return $format; - } - } - - return $default; - } - - /** - * Get the bearer token from the request headers. - * - * @return string|null - */ - public function bearerToken() - { - $header = $this->header('Authorization', ''); - - if (Str::startsWith($header, 'Bearer ')) { - return Str::substr($header, 7); - } - } - /** * Create an Illuminate request from a Symfony instance. * @@ -840,9 +332,7 @@ public static function createFromBase(SymfonyRequest $request) $content = $request->content; $request = (new static)->duplicate( - $request->query->all(), $request->request->all(), $request->attributes->all(), - $request->cookies->all(), $request->files->all(), $request->server->all() ); diff --git a/src/Illuminate/Http/Response.php b/src/Illuminate/Http/Response.php index 6a498a295fa0..aa1f475229e8 100755 --- a/src/Illuminate/Http/Response.php +++ b/src/Illuminate/Http/Response.php @@ -48,6 +48,20 @@ public function setContent($content) return parent::setContent($content); } + /** + * Determine if the given content should be turned into JSON. + * + * @param mixed $content + * @return bool + */ + protected function shouldBeJson($content) + { + return $content instanceof Jsonable || + $content instanceof ArrayObject || + $content instanceof JsonSerializable || + is_array($content); + } + /** * Morph the given content into JSON. * @@ -63,20 +77,6 @@ protected function morphToJson($content) return json_encode($content); } - /** - * Determine if the given content should be turned into JSON. - * - * @param mixed $content - * @return bool - */ - protected function shouldBeJson($content) - { - return $content instanceof Jsonable || - $content instanceof ArrayObject || - $content instanceof JsonSerializable || - is_array($content); - } - /** * Get the original response content. * diff --git a/src/Illuminate/Http/UploadedFile.php b/src/Illuminate/Http/UploadedFile.php index d91f61ed36ef..1cce63e0c191 100644 --- a/src/Illuminate/Http/UploadedFile.php +++ b/src/Illuminate/Http/UploadedFile.php @@ -21,11 +21,7 @@ class UploadedFile extends SymfonyUploadedFile */ public function store($path, $options = []) { - if (is_string($options)) { - $options = ['disk' => $options]; - } - - return $this->storeAs($path, $this->hashName(), $options); + return $this->storeAs($path, $this->hashName(), $this->parseOptions($options)); } /** @@ -37,9 +33,7 @@ public function store($path, $options = []) */ public function storePublicly($path, $options = []) { - if (is_string($options)) { - $options = ['disk' => $options]; - } + $options = $this->parseOptions($options); $options['visibility'] = 'public'; @@ -56,9 +50,7 @@ public function storePublicly($path, $options = []) */ public function storePubliclyAs($path, $name, $options = []) { - if (is_string($options)) { - $options = ['disk' => $options]; - } + $options = $this->parseOptions($options); $options['visibility'] = 'public'; @@ -75,11 +67,11 @@ public function storePubliclyAs($path, $name, $options = []) */ public function storeAs($path, $name, $options = []) { - $factory = Container::getInstance()->make(FilesystemFactory::class); - $disk = Arr::pull($options, 'disk'); - return $factory->disk($disk)->putFileAs($path, $this, $name, $options); + return Container::getInstance()->make(FilesystemFactory::class)->disk($disk)->putFileAs( + $path, $this, $name, $options + ); } /** @@ -100,4 +92,19 @@ public static function createFromBase(SymfonyUploadedFile $file, $test = false) $test ); } + + /** + * Parse and format the given options. + * + * @param array|string $options + * @return array + */ + protected function parseOptions($options) + { + if (is_string($options)) { + $options = ['disk' => $options]; + } + + return $options; + } }